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.

3574 lines
129 KiB

  1. /******************************************************************************
  2. Source File: Generic Font Information.CPP
  3. This implements the CFontInfo and all related classes, which describe printer
  4. fonts in all the detail necessary to satisfy all these different operating
  5. systems.
  6. Copyright (c) 1997 by Microsoft Corporation. All Rights Reserved.
  7. A Pretty Penny Enterprises Production
  8. Change History:
  9. 03-03-1997 Bob_Kjelgaard@Prodigy.Net Began work on this monster
  10. 02-01-1998 norzilla@asccessone.com aka Rick Mallonee rewrote nearly the whole thing.
  11. ******************************************************************************/
  12. #include "StdAfx.H"
  13. #include <gpdparse.h>
  14. #include "MiniDev.H"
  15. #include "utility.h"
  16. #include "FontInfo.H"
  17. #include "ChildFrm.H" // Definition of Tool Tips Property Page class
  18. #include "comctrls.h"
  19. #include "FontView.H"
  20. #include <uni16res.h>
  21. #include "rcfile.h"
  22. #include "ProjRec.H"
  23. static const double gdConvertRadToDegree = 900.0 / atan2(1.0, 0.0); // A handy constant for converting radians to 10's of a degree
  24. static CCodePageInformation* pccpi = NULL ; // Use a static CCodePageInformation to derive more benefit from caching
  25. /******************************************************************************
  26. CKern
  27. This class encapsulates the kerning pair structure. It's pretty trivial.
  28. The CFontInfo class maintains an array of these.
  29. %
  30. ******************************************************************************/
  31. class CKern : public CObject
  32. {
  33. FD_KERNINGPAIR m_fdkp;
  34. public:
  35. CKern() { m_fdkp.wcFirst = m_fdkp.wcSecond = m_fdkp.fwdKern = 0; }
  36. CKern(FD_KERNINGPAIR& fdkp) { m_fdkp = fdkp; }
  37. CKern(WCHAR wcf, WCHAR wcs, short sa) {
  38. m_fdkp.wcFirst = wcf ;
  39. m_fdkp.wcSecond = wcs ;
  40. m_fdkp.fwdKern = sa ;
  41. }
  42. WCHAR First() const { return m_fdkp.wcFirst; }
  43. WCHAR Second() const { return m_fdkp.wcSecond; }
  44. short Amount() const { return m_fdkp.fwdKern; }
  45. void SetAmount(short sNew) { m_fdkp.fwdKern = sNew; }
  46. void SetAll(WCHAR wcf, WCHAR wcs, short sa) {
  47. m_fdkp.wcFirst = wcf ;
  48. m_fdkp.wcSecond = wcs ;
  49. m_fdkp.fwdKern = sa ;
  50. }
  51. void Store(CFile& cf) { cf.Write(&m_fdkp, sizeof m_fdkp); }
  52. };
  53. /******************************************************************************
  54. CFontDifference class
  55. This class handles the requisite information content for the Font Difference
  56. structure involved with Font Simulation.
  57. ******************************************************************************/
  58. CFontDifference::CFontDifference(PBYTE pb, CBasicNode *pcbn)
  59. {
  60. FONTDIFF *pfd = (FONTDIFF *) pb;
  61. m_pcbnOwner = pcbn;
  62. m_cwaMetrics.Add(pfd -> usWinWeight);
  63. m_cwaMetrics.Add(pfd -> fwdMaxCharInc);
  64. m_cwaMetrics.Add(pfd -> fwdAveCharWidth);
  65. // NOTE: The conversion done in this statement is reversed in a statement
  66. // in the CFontDifference::Store() routine. For whatever reason,
  67. // this two steps can repeatedly reduce the user supplied value by
  68. // 1. To prevent this, 1 is added back in the following statement.
  69. m_cwaMetrics.Add((WORD) (gdConvertRadToDegree *
  70. atan2((double) pfd -> ptlCaret.x, (double) pfd -> ptlCaret.y)) + 1);
  71. }
  72. /******************************************************************************
  73. CFontDifference::SetMetric
  74. This function will modify one of the four metrics, if it is new, and it meets
  75. our criteria (Max >= Average, 0 <= Angle < 900, Weight <= 1000). Errors are
  76. reported via a public enum return code.
  77. ******************************************************************************/
  78. WORD CFontDifference::SetMetric(unsigned u, WORD wNew)
  79. {
  80. if (wNew == m_cwaMetrics[u]) return OK;
  81. /* Verification isn't needed and removing it solves other problems in the
  82. UFM Editor.
  83. switch (u)
  84. {
  85. case Max: if (wNew < m_cwaMetrics[Average]) return Reversed;
  86. break;
  87. case Average: if (wNew > m_cwaMetrics[Max]) return Reversed;
  88. break;
  89. case Weight: if (wNew > 1000) return TooBig;
  90. break;
  91. default: if (wNew > 899) return TooBig; // Angle
  92. }
  93. */
  94. gdConvertRadToDegree;
  95. m_cwaMetrics[u] = wNew;
  96. m_pcbnOwner -> Changed();
  97. return OK;
  98. }
  99. /******************************************************************************
  100. CFontDifference::Store(CFile& cf)
  101. This member creates a FONTDIFF structure, fills it, and writes it to the
  102. given file. The big calculation is the x and y components for the italic
  103. angle, if there is one.
  104. ******************************************************************************/
  105. void CFontDifference::Store(CFile& cf, WORD wfSelection)
  106. {
  107. FONTDIFF fd = {0, 0, 0, 0, m_cwaMetrics[Weight], wfSelection,
  108. m_cwaMetrics[Average], m_cwaMetrics[Max]};
  109. fd.bWeight = (m_cwaMetrics[Weight] >= FW_BOLD) ? PAN_WEIGHT_BOLD :
  110. (m_cwaMetrics[Weight] > FW_EXTRALIGHT) ?
  111. PAN_WEIGHT_MEDIUM : PAN_WEIGHT_LIGHT;
  112. if(gdConvertRadToDegree) // raid 116588 Prefix :: constant value;
  113. fd.ptlCaret.x = !m_cwaMetrics[Angle] ? 0 :
  114. (long) (10000.0 * tan(((double) m_cwaMetrics[Angle]) / gdConvertRadToDegree));
  115. fd.ptlCaret.y = m_cwaMetrics[Angle] ? 10000 : 1;
  116. cf.Write(&fd, sizeof fd);
  117. }
  118. /******************************************************************************
  119. And now, for the hardest working class in show business (and a personal friend
  120. of mine):
  121. CFontInfo class
  122. This class encapsulates all of the font knowledge this application needs.
  123. ******************************************************************************/
  124. IMPLEMENT_SERIAL(CFontInfo, CProjectNode, 0)
  125. /******************************************************************************
  126. CFontInfo::MapPFM
  127. This loads a PFM format file, if it isn't already loaded.
  128. ******************************************************************************/
  129. BOOL CFontInfo::MapPFM() {
  130. if (m_cbaPFM.GetSize())
  131. return TRUE; // Already has been loaded!
  132. try {
  133. CFile cfLoad(m_csSource, CFile::modeRead | CFile::shareDenyWrite);
  134. m_cbaPFM.SetSize(cfLoad.GetLength());
  135. cfLoad.Read(m_cbaPFM.GetData(), cfLoad.GetLength());
  136. }
  137. catch (CException *pce) {
  138. pce -> ReportError();
  139. pce -> Delete();
  140. m_cbaPFM.RemoveAll();
  141. return FALSE;
  142. }
  143. return TRUE;
  144. }
  145. /******************************************************************************
  146. CFontInfo::GetTranslation
  147. This loads a PFM format file and gets the default CTT ID from it. Nothing
  148. else is done.
  149. ******************************************************************************/
  150. extern "C" int ICttID2GttID(long lPredefinedCTTID);
  151. int CFontInfo::GetTranslation(CSafeObArray& csoagtts)
  152. {
  153. // PFM file structures- these are declared at this level to keep them off
  154. // the master class list for the project.
  155. #pragma pack(1) // The following is byte-aligned
  156. struct sPFMHeader {
  157. WORD m_wType, m_wPoints, m_wVertRes, m_wHorizRes, m_wAscent,
  158. m_wInternalLeading, m_wExternalLeading;
  159. BYTE m_bfItalic, m_bfUnderline, m_bfStrikeOut;
  160. WORD m_wWeight;
  161. BYTE m_bCharSet;
  162. WORD m_wPixWidth, m_wPixHeight;
  163. BYTE m_bfPitchAndFamily;
  164. WORD m_wAvgWidth, m_wMaxWidth;
  165. BYTE m_bFirstChar, m_bLastChar, m_bDefaultChar, m_bBreakChar;
  166. WORD m_wcbWidth;
  167. DWORD m_dwDevice, m_dwFace, m_dwBitsPointer, m_dwofBits;
  168. BYTE m_bReserved;
  169. };
  170. struct sPFMExtension {
  171. WORD m_wcbRemaining; // From this point on
  172. DWORD m_dwofExtMetrics, m_dwofExtentTable, m_dwofOriginTable,
  173. m_dwofPairKernTable, m_dwofTrackKernTable, m_dwofDriverInfo,
  174. m_dwReserved;
  175. };
  176. #pragma pack (2) // Everything else has word alignment
  177. struct sOldKernPair {
  178. union {
  179. BYTE m_abEach[2];
  180. WORD m_wBoth;
  181. };
  182. short m_sAmount;
  183. };
  184. struct sKernTrack {
  185. short m_sDegree, m_sMinSize, m_sMinAmount, m_sMaxSize, m_sMaxAmount;
  186. };
  187. struct sPFMDriverInfo {
  188. enum {CurrentVersion = 0x200};
  189. enum {CannotItalicize = 1, CannotUnderline, SendCRAfterUsing = 4,
  190. CannotMakeBold = 8, CannotDoubleUnderline = 0x10,
  191. CannotStrikeThru = 0x20, BackspaceForPairs = 0x40};
  192. WORD m_wcbThis, m_wVersion, m_wfCapabilities, m_widThis, m_wAdjustY,
  193. m_wYMovement, m_widCTT, m_wUnderlinePosition,
  194. m_wDoubleUnderlinePosition, m_wStrikeThruPosition;
  195. DWORD m_dwofSelect, m_dwofDeselect;
  196. WORD m_wPrivateData; /* Used in DeskJet driver for font enumerations */
  197. short m_sShiftFromCenter;
  198. enum {HPIntelliFont, TrueType, PPDSScalable, CapsL, OEMType1, OEMType2};
  199. WORD m_wFontType;
  200. };
  201. #pragma pack() // We now return control to you
  202. if (!MapPFM())
  203. return -IDS_FileReadError ;
  204. // Now, map out the rest of the pieces of the structure.
  205. union {
  206. BYTE *pbPFM; // Base of the file for offsets!
  207. sPFMHeader *pspfmh;
  208. };
  209. pbPFM = m_cbaPFM.GetData();
  210. // Screen out evil files- part 1: is length sufficient?
  211. unsigned uSize = sizeof (sPFMHeader) + sizeof (sPFMExtension) +
  212. sizeof (sPFMDriverInfo);
  213. if ((unsigned) m_cbaPFM.GetSize() < uSize)
  214. return -IDS_PFMTooSmall ;
  215. // YA Sanity check
  216. if (pspfmh -> m_bLastChar < pspfmh -> m_bFirstChar)
  217. return -IDS_PFMCharError ;
  218. // Width table, if there is one.
  219. WORD *pwWidth = pspfmh -> m_wPixWidth ? NULL : (PWORD) (pspfmh + 1);
  220. uSize += !!pwWidth * sizeof (WORD) *
  221. (2 + pspfmh -> m_bLastChar - pspfmh -> m_bFirstChar);
  222. // Screen out evil files- part 2: is length still sufficient?
  223. if ((unsigned) m_cbaPFM.GetSize() < uSize)
  224. return -IDS_PFMTooSmall ;
  225. // PFMExtension follows width table, otherwise the header
  226. sPFMExtension *pspfme = pwWidth ? (sPFMExtension *)
  227. (pwWidth + 2 + pspfmh -> m_bLastChar - pspfmh -> m_bFirstChar) :
  228. (sPFMExtension *) (pspfmh + 1);
  229. // Penultimate sanity check- is the driver info offset real?
  230. if ((unsigned) m_cbaPFM.GetSize() <
  231. pspfme -> m_dwofDriverInfo + sizeof (sPFMDriverInfo))
  232. return -IDS_BadPFMInfoOffset ;
  233. // Text Metrics, DriverInfo and others are pointed at by PFM
  234. // Extension.
  235. sPFMDriverInfo *pspfmdi =
  236. (sPFMDriverInfo *) (pbPFM + pspfme -> m_dwofDriverInfo);
  237. // Final sanity check- is the driver info version real?
  238. if (pspfmdi -> m_wVersion > sPFMDriverInfo::CurrentVersion)
  239. return -IDS_BadPFMInfoVersion ;
  240. // See if the original CTT ID needs to be converted to a new codepage
  241. // number. If not, leave it alone. In any case, set the font's GTT ID.
  242. //TRACE("GetTrans: UFM = %s CTT ID = %d GTT ID = %d\n", Name(), pspfmdi -> m_widCTT, ICttID2GttID((long) (short) pspfmdi -> m_widCTT)) ;
  243. // m_widTranslation = (WORD) ICttID2GttID((long) (short) pspfmdi -> m_widCTT); // rm ori
  244. m_lGlyphSetDataRCID = (WORD) ICttID2GttID((long) (short) pspfmdi -> m_widCTT); // rm new
  245. if (!m_lGlyphSetDataRCID) { // Raid 135623
  246. switch (pspfmh ->m_bCharSet) {
  247. case SHIFTJIS_CHARSET:
  248. m_lGlyphSetDataRCID = -17;
  249. break;
  250. case GB2312_CHARSET:
  251. m_lGlyphSetDataRCID = -16;
  252. break;
  253. case HANGEUL_CHARSET:
  254. case JOHAB_CHARSET:
  255. m_lGlyphSetDataRCID = -18;
  256. break;
  257. case CHINESEBIG5_CHARSET:
  258. m_lGlyphSetDataRCID = -10;
  259. break;
  260. } ;
  261. } ;
  262. // GTTs will be renumbered when the new, W2K RC file is written. Because of
  263. // this, the GTT ID set above needs to be translated to the new number. This
  264. // number corresponds to the GTT's position in GlyphTable. NOTE: The ID is
  265. // not changed if it is <= 0. (The IDs in the GlyphMaps will be changed in
  266. // CDriverResources::LoadFontData().)
  267. if (m_lGlyphSetDataRCID > 0 && m_lGlyphSetDataRCID == pspfmdi->m_widCTT) {
  268. for (unsigned uGTT = 0; uGTT < csoagtts.GetSize(); uGTT++)
  269. if (m_lGlyphSetDataRCID
  270. == ((LONG) ((CGlyphMap *) csoagtts[uGTT])->nGetRCID()))
  271. m_lGlyphSetDataRCID = uGTT + 1 ;
  272. } ;
  273. Changed();
  274. return 0 ;
  275. }
  276. /******************************************************************************
  277. CFontInfo::CalculateWidths()
  278. This member function is needed whenever a change is made to a variable pitch
  279. font's width table, or equally well, whenever an arbitrary table is picked up
  280. by a formerly fixed pitch font. It calculates the width using the approved
  281. algorithm (average means average of 26 lower-case plus the space, unless they
  282. don't exist, in which case it is of all non-zero widths).
  283. ******************************************************************************/
  284. void CFontInfo::CalculateWidths()
  285. {
  286. // m_wMaximumIncrement = 0; // Assume max width is 0, then prove otherwise. Also collect the
  287. // raw information needed to correctly calculate the average width.
  288. unsigned uPointsToAverage = 0, uOverallWidth = 0, uAverageWidth = 0,
  289. uZeroPoints = 0;
  290. for (unsigned u = 0; u < (unsigned) m_cpaGlyphs.GetSize(); u++)
  291. {
  292. WORD wWidth = m_cwaWidth[u];;
  293. m_IFIMETRICS.fwdMaxCharInc = max(m_IFIMETRICS.fwdMaxCharInc, wWidth); // rm new
  294. // m_wMaximumIncrement = max(m_wMaximumIncrement, wWidth); // rm ori
  295. uOverallWidth += wWidth;
  296. if (!wWidth) uZeroPoints++;
  297. // if (Glyph(u).CodePoint() == m_cwaSignificant[Break] || // rm ori
  298. if (Glyph(u).CodePoint() == m_IFIMETRICS.wcBreakChar || // rm new
  299. (Glyph(u).CodePoint() >= (WORD) 'a' &&
  300. Glyph(u).CodePoint() <= (WORD) 'z'))
  301. {
  302. uAverageWidth += wWidth;
  303. uPointsToAverage++;
  304. }
  305. }
  306. // If we averaged 27 points, then this is the correct width. Otherwise,
  307. // We average all of the widths. cf the IFIMETRICS description in DDK
  308. m_IFIMETRICS.fwdAveCharWidth = (uPointsToAverage == 27) ? // rm new
  309. // m_wAverageWidth = (uPointsToAverage == 27) ? // rm ori
  310. (WORD) (0.5 + ((double) uAverageWidth) / 27.0) :
  311. (WORD) (0.5 + (((double) uOverallWidth) / (double) (u - uZeroPoints)));
  312. }
  313. /******************************************************************************
  314. CFontInfo::CFontInfo()
  315. This class constructor has a lot of work to do. Not only does it have to
  316. initialize 5 zillion fields, it has to build the context menu list, and a few
  317. other glorious items of that ilk.
  318. ******************************************************************************/
  319. CFontInfo::CFontInfo()
  320. {
  321. m_fEXTTEXTMETRIC = FALSE; // rm new
  322. m_pcmdt = NULL;
  323. m_pcgmTranslation = NULL;
  324. m_pcfdBold = m_pcfdItalic = m_pcfdBoth = NULL;
  325. m_cfn.SetExtension(_T(".UFM"));
  326. m_ulDefaultCodepage = 0 ;
  327. m_bRCIDChanged = 0 ; // raid 0003
  328. // m_bCharacterSet = m_bPitchAndFamily = 0; // rm no longer needed
  329. // m_wMaximumIncrement = m_wfStyle = m_wWeight = m_wAverageWidth = // rm ori
  330. // m_wHeight = m_widTranslation = 0; // rm ori
  331. m_wHeight = 0;
  332. m_lGlyphSetDataRCID = 0; // rm new
  333. // m_bLocation = m_bTechnology = m_bfGeneral = 0; // rm ori
  334. // m_wType = m_fCaps = 0; // rm no longer needed
  335. // m_bScalable = FALSE; // rm no longer needed
  336. // m_wXResolution = m_wYResolution = m_wPrivateData = 0; // rm ori
  337. // m_sPreAdjustY = m_sPostAdjustY = m_sCenterAdjustment = 0; // rm ori
  338. // m_wXRes = m_wYRes = m_wPrivateData = 0; // rm no longer needed
  339. // m_sYAdjust = m_sYMoved = m_sCenterAdjustment = 0; // rm no longer needed
  340. m_wMaxScale = m_wMinScale = m_wScaleDevice = 0;
  341. // m_bfScaleOrientation = 0;
  342. m_cwaSpecial.InsertAt(0, 0, 1 + InternalLeading); // Initialize this array.
  343. // Build the context menu control
  344. m_cwaMenuID.Add(ID_OpenItem);
  345. m_cwaMenuID.Add(ID_CopyItem);
  346. m_cwaMenuID.Add(ID_RenameItem);
  347. m_cwaMenuID.Add(ID_DeleteItem);
  348. m_cwaMenuID.Add(0);
  349. m_cwaMenuID.Add(ID_ExpandBranch);
  350. m_cwaMenuID.Add(ID_CollapseBranch);
  351. // Allocate a CCodePageInformation class if needed.
  352. if (pccpi == NULL)
  353. pccpi = new CCodePageInformation ;
  354. // Assume the font is NOT being loaded from a workspace.
  355. m_bLoadedByWorkspace = false ;
  356. // Assume that a GTT/CP will be found for the UFM.
  357. m_bWSLoadButNoGTTCP = false ;
  358. // Another method is used for now.
  359. //
  360. // // Assume there is no width table offset and that the font not variable
  361. // // pitch. These variables are both used to determine if this is a variable
  362. // // pitch font.
  363. //
  364. // m_loWidthTable = 0 ;
  365. // m_IFIMETRICS.jWinPitchAndFamily = 0 ;
  366. m_ctReloadWidthsTimeStamp = (time_t) 0 ; // Widths never reloaded
  367. }
  368. /******************************************************************************
  369. CFontInfo::CFontInfo(const CFontInfo& cfiRef, WORD widCTT)
  370. This class constructor duplicates an existing font, but changes the CTT ID,
  371. and generates a new name and file name accordingly
  372. ******************************************************************************/
  373. CFontInfo::CFontInfo(const CFontInfo& cfiRef, WORD widCTT) // r31
  374. {
  375. m_fEXTTEXTMETRIC = FALSE; // rm new
  376. m_pcmdt = cfiRef.m_pcmdt;
  377. m_pcfdBold = m_pcfdItalic = m_pcfdBoth = NULL;
  378. m_pcgmTranslation = NULL;
  379. m_cfn.SetExtension(_T(".UFM"));
  380. CString csWork;
  381. // Generate what will hopefully be a unique file name for the UFM
  382. ReTitle(cfiRef.Name()) ;
  383. m_cfn.UniqueName(true, true, cfiRef.m_cfn.Path()) ;
  384. //m_cfn.Rename(cfiRef.m_cfn.Path() + cfiRef.Name() + csWork);
  385. // Generate a new display name for the UFM using the CTT number
  386. csWork.Format(_T("(CTT %d)"), (long)(short)widCTT); // r 31
  387. m_csSource = cfiRef.m_csSource;
  388. Rename(cfiRef.Name() + csWork);
  389. // m_bCharacterSet = m_bPitchAndFamily = 0; // rm no longer needed
  390. // m_wMaximumIncrement = m_wfStyle = m_wWeight = m_wAverageWidth = // rm ori
  391. m_wHeight = 0;
  392. // m_bLocation = m_bTechnology = m_bfGeneral = 0; // rm ori
  393. // m_wType = m_fCaps = 0; // rm no longer needed
  394. // m_bScalable = FALSE; // rm no longer needed
  395. // m_wXResolution = m_wYResolution = m_wPrivateData = 0; // rm ori
  396. // m_sPreAdjustY = m_sPostAdjustY = m_sCenterAdjustment = 0; // rm ori
  397. // m_wXRes = m_wYRes = m_wPrivateData = 0; // rm no longer needed
  398. // m_sYAdjust = m_sYMoved = m_sCenterAdjustment = 0; // rm no longer needed
  399. m_wMaxScale = m_wMinScale = m_wScaleDevice = 0;
  400. // m_bfScaleOrientation = 0;
  401. m_cwaSpecial.InsertAt(0, 0, 1 + InternalLeading); // Initialize this array.
  402. // m_widTranslation = widCTT; // rm ori
  403. m_lGlyphSetDataRCID = widCTT; // rm new
  404. // Build the context menu control
  405. m_cwaMenuID.Copy(cfiRef.m_cwaMenuID);
  406. // Allocate a CCodePageInformation class if needed.
  407. if (pccpi == NULL)
  408. pccpi = new CCodePageInformation ;
  409. // Assume the font is NOT being loaded from a workspace.
  410. m_bLoadedByWorkspace = false ;
  411. // Assume that a GTT/CP will be found for the UFM.
  412. m_bWSLoadButNoGTTCP = false ;
  413. m_ctReloadWidthsTimeStamp = (time_t) 0 ; // Widths never reloaded
  414. }
  415. CFontInfo::~CFontInfo()
  416. {
  417. if (m_pcfdBold) delete m_pcfdBold;
  418. if (m_pcfdItalic) delete m_pcfdItalic;
  419. if (m_pcfdBoth) delete m_pcfdBoth;
  420. }
  421. /******************************************************************************
  422. CFontInfo::GTTDescription
  423. This returns a CString naming the GTT associated with this font. It will
  424. come from the workspace if the font is a resource, or the string table, if it
  425. is predefined.
  426. ******************************************************************************/
  427. CString CFontInfo::GTTDescription() const {
  428. if (m_pcgmTranslation)
  429. return m_pcgmTranslation -> Name();
  430. CString csName;
  431. // if ((short) m_widTranslation <= 0) // rm ori
  432. if ((short) m_lGlyphSetDataRCID <= 0) // r31 re visit // rm new
  433. // csName.LoadString(IDS_DefaultPage + (short) m_widTranslation); // rm ori
  434. csName.LoadString(IDS_DefaultPage + (short) m_lGlyphSetDataRCID); // rm new
  435. if (!csName.GetLength())
  436. // csName.Format(IDS_ResourceID, (short) m_widTranslation); // rm ori
  437. csName.Format(IDS_ResourceID, (short) m_lGlyphSetDataRCID); // rm new
  438. return csName;
  439. }
  440. /******************************************************************************
  441. CFontInfo::InterceptItalic
  442. This calculates where a line drawn at the italic slant angle would intercept
  443. a rectangle the height of the ascender, and twice the maximum width of the
  444. font. It is used to help draw the image of this line in the font editor.
  445. ******************************************************************************/
  446. /*
  447. void CFontInfo::InterceptItalic(CPoint& cpt) const {
  448. if (!m _cwaSpecial[ItalicAngle]) { // Nothing
  449. cpt.x = 5;
  450. cpt.y = 0;
  451. return;
  452. }
  453. // First, assume we will hit the top- it's almost always true.
  454. cpt.x = 5 + (long) (0.5 + tan(((double) m _cwaSpecial[ItalicAngle]) /
  455. gdConvertRadToDegree) * ((double) m_IFIMETRICS.fwdWinAscender); // rm new
  456. // gdConvertRadToDegree) * ((double) m _cwaSpecial[Baseline])); rm ori
  457. if (cpt.x <= -5 + 2 * m_wMaximumIncrement) {
  458. cpt.y = 0;
  459. return;
  460. }
  461. // OK, assume the opposite
  462. cpt.y = (long) (0.5 + tan(((double) (900 - m _cwaSpecial[ItalicAngle])) /
  463. gdConvertRadToDegree) * ((double) (-10 + 2 * m_wMaximumIncrement)));
  464. cpt.x = -5 + 2 * m_wMaximumIncrement;
  465. }
  466. */
  467. /******************************************************************************
  468. CFontInfo::CompareWidths
  469. This compares the character widths for two indices, and returns, Less, More,
  470. or Equal, as need be. It is not const, because Glyph() is not, and I've
  471. already got a bazillion member functions.
  472. ******************************************************************************/
  473. unsigned CFontInfo::CompareWidths(unsigned u1, unsigned u2) {
  474. _ASSERT(IsVariableWidth() && u1 < (unsigned) m_cpaGlyphs.GetSize() &&
  475. u2 < (unsigned) m_cpaGlyphs.GetSize());
  476. return (m_cwaWidth[u1] < m_cwaWidth[u2]) ? Less :
  477. (m_cwaWidth[u1] > m_cwaWidth[u2]) ? More : Equal;
  478. }
  479. /******************************************************************************
  480. CFontInfo::MapKerning
  481. This maps out the available code points, and the kern pairs in both
  482. directions, into a CWordArray and a pair of CSafeMapWordToObs (where the
  483. underlying CObjects are CMapWordToDWords), respectively. This allows the
  484. Add Kerning Pair dialog to screen out already defined pairs, and invalid code
  485. points.
  486. ******************************************************************************/
  487. void CFontInfo::MapKerning(CSafeMapWordToOb& csmw2o1,
  488. CSafeMapWordToOb& csmw2o2,
  489. CWordArray& cwaPoints) {
  490. // If this isn't variable width, then we'll need to suck up some glyph
  491. // data, temporarily.
  492. BOOL bDispose = !IsVariableWidth();
  493. if (bDispose)
  494. m_pcgmTranslation -> Collect(m_cpaGlyphs);
  495. unsigned rm = m_pcgmTranslation->Glyphs(); // rm
  496. for (unsigned u = 0; u < m_pcgmTranslation -> Glyphs(); u++)
  497. if (!DBCSFont() || Glyph(u).CodePoint() < 0x80)
  498. cwaPoints.Add(Glyph(u).CodePoint());
  499. else
  500. break;
  501. if (bDispose)
  502. m_cpaGlyphs.RemoveAll();
  503. for (u = 0; u < m_csoaKern.GetSize(); u++) {
  504. CKern& ck = *(CKern *) m_csoaKern[u];
  505. union {
  506. CObject *pco;
  507. CMapWordToDWord *pcmw2d;
  508. };
  509. // Map first word to second
  510. if (csmw2o1.Lookup(ck.First(), pco)) {
  511. _ASSERT(!pcmw2d -> operator[](ck.Second()));
  512. pcmw2d -> operator[](ck.Second()) = (DWORD) ck.Amount();
  513. }
  514. else {
  515. CMapWordToDWord *pcmw2d = new CMapWordToDWord;
  516. pcmw2d -> operator[](ck.Second()) = (DWORD) ck.Amount();
  517. csmw2o1[ck.First()] = pcmw2d;
  518. }
  519. // Now the other direction
  520. if (csmw2o2.Lookup(ck.Second(), pco)) {
  521. _ASSERT(!pcmw2d -> operator[](ck.First()));
  522. pcmw2d -> operator[](ck.First()) = (DWORD) ck.Amount();
  523. }
  524. else {
  525. CMapWordToDWord *pcmw2d = new CMapWordToDWord;
  526. pcmw2d -> operator[](ck.First()) = (DWORD) ck.Amount();
  527. csmw2o2[ck.Second()] = pcmw2d;
  528. }
  529. }
  530. }
  531. /******************************************************************************
  532. CFontInfo::CompareKernAmount
  533. This is an editor sort helper- it tells how two kern amounts compare by
  534. index.
  535. ******************************************************************************/
  536. unsigned CFontInfo::CompareKernAmount(unsigned u1, unsigned u2) const {
  537. CKern &ck1 = *(CKern *) m_csoaKern[u1], &ck2 = *(CKern *) m_csoaKern[u2];
  538. return (ck1.Amount() < ck2.Amount()) ? Less :
  539. (ck1.Amount() > ck2.Amount()) ? More : Equal;
  540. }
  541. /******************************************************************************
  542. CFontInfo::CompareKernFirst
  543. This is an editor sort helper- it tells how two kern first characters
  544. compare by index.
  545. ******************************************************************************/
  546. unsigned CFontInfo::CompareKernFirst(unsigned u1, unsigned u2) const {
  547. CKern &ck1 = *(CKern *) m_csoaKern[u1], &ck2 = *(CKern *) m_csoaKern[u2];
  548. return (ck1.First() < ck2.First()) ? Less :
  549. (ck1.First() > ck2.First()) ? More : Equal;
  550. }
  551. /******************************************************************************
  552. CFontInfo::CompareKernSecond
  553. This is an editor sort helper- it tells how two kern second characters
  554. compare by index.
  555. ******************************************************************************/
  556. unsigned CFontInfo::CompareKernSecond(unsigned u1, unsigned u2) const {
  557. CKern &ck1 = *(CKern *) m_csoaKern[u1], &ck2 = *(CKern *) m_csoaKern[u2];
  558. return (ck1.Second() < ck2.Second()) ? Less :
  559. (ck1.Second() > ck2.Second()) ? More : Equal;
  560. }
  561. /******************************************************************************
  562. CFontInfo::GetKernFirst
  563. Return the kerning pairs' first character.
  564. ******************************************************************************/
  565. WCHAR CFontInfo::GetKernFirst(unsigned u) const
  566. {
  567. CKern &ck = *(CKern *) m_csoaKern[u] ;
  568. return (ck.First()) ;
  569. }
  570. /******************************************************************************
  571. CFontInfo::GetKernSecond
  572. Return the kerning pairs' second character.
  573. ******************************************************************************/
  574. WCHAR CFontInfo::GetKernSecond(unsigned u) const
  575. {
  576. CKern &ck = *(CKern *) m_csoaKern[u] ;
  577. return (ck.Second()) ;
  578. }
  579. /******************************************************************************
  580. CFontInfo::GetKernAmount
  581. Return the kerning pairs' kerning amount.
  582. ******************************************************************************/
  583. short CFontInfo::GetKernAmount(unsigned u) const
  584. {
  585. CKern &ck = *(CKern *) m_csoaKern[u] ;
  586. return (ck.Amount()) ;
  587. }
  588. /******************************************************************************
  589. CFontInfo::SetSourceName
  590. This takes and stores the source file name so we can load and convert later.
  591. This takes and stores the name for the project node for this UFM. It begins
  592. with the PFM file name. If the extension is PFM, it is used. Otherwise, the
  593. dot in the file name is changed to an underscore and the whole thing is used.
  594. ******************************************************************************/
  595. void CFontInfo::SetSourceName(LPCTSTR lpstrNew) {
  596. m_csSource = lpstrNew;
  597. m_csName = m_csSource.Mid(m_csSource.ReverseFind(_T('\\')) + 1);
  598. if (m_csName.Find(_T('.')) >= 0)
  599. if (m_csName.Right(4).CompareNoCase(_T(".PFM"))) {
  600. m_csName.SetAt(m_csName.Find(_T('.')), _T('_'));
  601. CProjectNode::Rename(m_csName);
  602. }
  603. else
  604. CProjectNode::Rename(m_csName.Left(m_csName.Find(_T('.'))));
  605. else
  606. CProjectNode::Rename(m_csName);
  607. }
  608. /******************************************************************************
  609. CFontInfo::SetFileName
  610. This sets the new file name. It is done differently than in SetSourceName()
  611. because the base file name must not be more than 8 characters long. (The
  612. extra info is left in the node name by SetSourceName() because it is useful
  613. there and it has no length limit.)
  614. ******************************************************************************/
  615. BOOL CFontInfo::SetFileName(LPCTSTR lpstrNew)
  616. {
  617. CString csnew ; // CString version of input parameter
  618. csnew = lpstrNew ;
  619. // If the input filespec contains an extension, remove it and pass the
  620. // resulting string to the file node's rename routine. Otherwise, just
  621. // pass the original string to the rename routine.
  622. //
  623. // This check is complicated by the fact that one of the path components
  624. // might have a dot in it too. We need to check for the last dot and make
  625. // sure it comes before a path separator.
  626. if (csnew.ReverseFind(_T('.')) > csnew.ReverseFind(_T('\\')))
  627. return m_cfn.Rename(csnew.Left(csnew.ReverseFind(_T('.')))) ;
  628. else
  629. return m_cfn.Rename(csnew) ;
  630. }
  631. /******************************************************************************
  632. CFontInfo::Generate
  633. This member generates the font information in one of the supported forms. I
  634. determine the desired form from the file's extension.
  635. ******************************************************************************/
  636. BOOL ConvertPFMToIFI(LPCTSTR lpstrPFM, LPCTSTR lpstrIFI, LPCTSTR lpstrUniq);
  637. extern "C" {
  638. BOOL BConvertPFM(LPBYTE lpbPFM, DWORD dwCodePage, LPBYTE lpbGTT,
  639. PWSTR pwstrUnique, LPCTSTR lpstrUFM, int iGTTID);
  640. DWORD DwGetCodePageFromGTTID(LONG lPredefinedCTTId);
  641. }
  642. int CFontInfo::Generate(CString csPath)
  643. {
  644. CString csExtension = csPath.Right(4);
  645. csExtension.MakeUpper();
  646. if (csExtension == _T(".IFI"))
  647. return ConvertPFMToIFI(m_csSource, csPath, m_csUnique);
  648. if (csExtension == _T(".UFM")) {
  649. if (!m_pcgmTranslation) {
  650. //CString csWork;
  651. // csWork.Format(IDS_BadCTTID, (LPCTSTR) m_csSource, (long) (short) m_widTranslation); // rm ori
  652. //csWork.Format(IDS_BadCTTID, (LPCTSTR) m_csSource, (long) (short) m_lGlyphSetDataRCID); // rm new
  653. //AfxMessageBox(csWork);
  654. return IDS_BadCTTID;
  655. }
  656. // Determine whether a GTT file or code page is to be used
  657. // DWORD dwCodePage = DwGetCodePageFromCTTID((LONG) - (short) m_widTranslation); // rm ori
  658. DWORD dwCodePage = DwGetCodePageFromGTTID((LONG) - (short) m_lGlyphSetDataRCID); // r 31 // rm new
  659. // Load the GTT file, if we need to. This handles predefined, as well
  660. CByteArray cbaMap;
  661. m_pcgmTranslation -> Load(cbaMap);
  662. if (!cbaMap.GetSize())
  663. return IDS_UFMGenError ;
  664. // Load the PFM file into memory (should already be there)
  665. if (!MapPFM())
  666. return IDS_UFMGenError ; // Couldn't load PFM- impossible at this point!
  667. // Convert the unique name string to Unicode
  668. CByteArray cbaIn;
  669. CWordArray cwaOut;
  670. cbaIn.SetSize(1 + m_csUnique.GetLength());
  671. if (!SUCCEEDED(StringCchCopyA((LPSTR) cbaIn.GetData(), cbaIn.GetSize(), (LPCTSTR) m_csUnique)))
  672. {
  673. return IDS_UFMGenError;
  674. }
  675. pccpi->Convert(cbaIn, cwaOut, GetACP());
  676. // DO IT!
  677. //TRACE("%s UFM has CP = %d and RCID = %d\n", Name(), dwCodePage, m_lGlyphSetDataRCID) ;
  678. // If both the code page and GTT ID are 0, set the code page to 1252.
  679. if (dwCodePage == 0 && m_lGlyphSetDataRCID == 0)
  680. dwCodePage = 1252 ;
  681. //TRACE("*** GTT Pointer = %d\n", cbaMap.GetData()) ;
  682. ASSERT(cbaMap.GetData()) ;
  683. BOOL brc = BConvertPFM(m_cbaPFM.GetData(), dwCodePage, cbaMap.GetData(),
  684. // cwaOut.GetData(), FileName(), (short) m_widTranslation); // rm ori
  685. cwaOut.GetData(), FileName(), (short) m_lGlyphSetDataRCID); //r 31 short -> INT // rm new
  686. return ((brc) ? 0 : IDS_UFMGenError) ;
  687. // return BConvertPFM(m_cbaPFM.GetData(), dwCodePage, cbaMap.GetData(),
  688. //// cwaOut.GetData(), FileName(), (short) m_widTranslation); // rm ori
  689. // cwaOut.GetData(), FileName(), (short) m_lGlyphSetDataRCID); // rm new
  690. }
  691. return 0 ;
  692. }
  693. /******************************************************************************
  694. CFontInfo::AddFamily
  695. This searches for the given name in the list of families, and adds it if it
  696. is not there. It returns TRUE if it succeeded.
  697. ******************************************************************************/
  698. BOOL CFontInfo::AddFamily(LPCTSTR lpstrNew) {
  699. for (unsigned u = 0; u < Families(); u++)
  700. if (!Family(u).CompareNoCase(lpstrNew))
  701. break;
  702. if (u < Families())
  703. return FALSE; // Already have it!
  704. try {
  705. m_csaFamily.Add(lpstrNew);
  706. }
  707. catch (CException * pce) {
  708. pce -> ReportError();
  709. pce -> Delete();
  710. return FALSE;
  711. }
  712. Changed();
  713. return TRUE;
  714. }
  715. /******************************************************************************
  716. CFontInfo::RemoveFamily
  717. This function removes the given family name from the list of aliases. This
  718. code is more robust than it needs to be- it'll remove duplicates, even though
  719. the add code won't allow them to be added. No telling what the input data
  720. looks like, though, is there?
  721. ******************************************************************************/
  722. void CFontInfo::RemoveFamily(LPCTSTR lpstrDead) {
  723. for (unsigned u = 0; u < Families(); u ++)
  724. if (!Family(u).CompareNoCase(lpstrDead)) {
  725. m_csaFamily.RemoveAt(u--); // Decrement so we don't miss one
  726. Changed();
  727. }
  728. }
  729. /*****************************************************************************
  730. CFontInfo::ChangePitch
  731. We exploit the fact that the widths are maintained in the CGlyphMap
  732. (actually the CGlyphHandle) class. All this method need do for a variable
  733. font flipping to fixed is to toss out the m_cpaGlyphs member's content. To
  734. flip to variable, collect the handles, then check the first one's width- if
  735. it's non-zero, then a previous transition from variable to fixed is being
  736. undone, and we can recycle the old values, thus keeping any edits that may
  737. have been lost. Otherwise, the trick code comes- the initial values get
  738. filled- what's tricky is that for a DBCS character set, only the SBCS values
  739. less than 0x80 can be variable.
  740. ******************************************************************************/
  741. void CFontInfo::ChangePitch(BOOL bFixed)
  742. {
  743. if (bFixed == !IsVariableWidth())
  744. return; // Nothing to change!
  745. if (bFixed)
  746. {
  747. m_cpaGlyphs.RemoveAll(); // CPtrArray doesn't delete anything
  748. m_IFIMETRICS.fwdAveCharWidth = DBCSFont() ? (1 + m_IFIMETRICS.fwdMaxCharInc) >> 1 : m_IFIMETRICS.fwdMaxCharInc; // rm new
  749. // m_wAverageWidth = DBCSFont() ? (1 + m_IFIMETRICS.fwdMaxCharInc) >> 1 : m_IFIMETRICS.fwdMaxCharInc; // rm ori
  750. // m_wAverageWidth = DBCSFont() ? (1 + m_wMaximumIncrement) >> 1 : m_wMaximumIncrement;
  751. Changed();
  752. return;
  753. }
  754. if (!m_pcgmTranslation) return; // Can't do this with no GTT available
  755. m_pcgmTranslation -> Collect(m_cpaGlyphs);
  756. if (!m_cwaWidth.GetSize())
  757. m_cwaWidth.InsertAt(0, 0, m_cpaGlyphs.GetSize());
  758. Changed(); // It sure has...
  759. if (!m_cpaGlyphs.GetSize() || m_cwaWidth[0])
  760. { // Update the maximum and average width if this is not DBCS
  761. if (!DBCSFont())
  762. CalculateWidths();
  763. return; // We did all that needed to be done
  764. }
  765. if (!DBCSFont()) {
  766. for (int i = 0; i < m_cpaGlyphs.GetSize(); i++)
  767. m_cwaWidth[i] = m_IFIMETRICS.fwdMaxCharInc; //m_wMaximumIncrement; // rm ori, rm new
  768. return;
  769. }
  770. for (int i = 0; i < m_cpaGlyphs.GetSize() && Glyph(i).CodePoint() < 0x80;)
  771. m_cwaWidth[i++] = m_IFIMETRICS.fwdAveCharWidth; //m_wAverageWidth; // rm ori, rm new // In DBCS, this is always it
  772. }
  773. /*****************************************************************************
  774. CFontInfo::SetScalability
  775. This is called to turn scalability on or off. All that really needs to be
  776. done is to establish values for the maximum and minimum scale, the font ->
  777. device units mapping members, and the lowercase ascender /descender, if this
  778. is the first time this information has changed.
  779. ******************************************************************************/
  780. /*void CFontInfo::SetScalability(BOOL bOn) {
  781. if (IsScalable() == !!bOn)
  782. return; // Nothing to change
  783. if (!bOn) {
  784. m_bScalable = FALSE;
  785. Changed();
  786. return;
  787. }
  788. m_bScalable = TRUE;
  789. Changed();
  790. if (m_wMaxScale && m_wMinScale && m_wMaxScale != m_wMinScale)
  791. return; // We've already got data.
  792. m_wMaxScale = m_wMinScale = m_wScaleDevice = m_wHeight - m_InternalLeading
  793. // m_wHeight - m _cwaSpecial[InternalLeading];
  794. // Flaky, but set the initial max and min to +- 1 point from nominal
  795. m_wMaxScale += m_wYResolution / 72;
  796. m_wMinScale -= m_wYResolution / 72;
  797. // Finally, set the lowercase ascender and descender to simple defaults
  798. m_Lowerd = m_IFIMETRICS.fwdWinAscender - m_InternalLeading;
  799. m_Lowerp = m_wHeight - m_IFIMETRICS.fwdWinAscender;
  800. }
  801. */
  802. /*****************************************************************************
  803. CFontInfo::SetSpecial
  804. This adjusts anything that may need adjusting if a special metric is
  805. altered.
  806. ******************************************************************************/
  807. void CFontInfo::SetSpecial(unsigned ufMetric, short sSpecial)
  808. {
  809. if (m_cwaSpecial[ufMetric] == (WORD) sSpecial) return; // Nothing changed
  810. m_cwaSpecial[ufMetric] = (WORD) sSpecial;
  811. switch (ufMetric)
  812. {
  813. case InternalLeading:
  814. // Adjust the scaling factors if need be
  815. if (m_wScaleDevice > m_wHeight - sSpecial) m_wScaleDevice = m_wHeight - sSpecial;
  816. if (m_wMinScale > m_wHeight - sSpecial) m_wMinScale = m_wHeight - sSpecial;
  817. }
  818. Changed();
  819. }
  820. /*****************************************************************************
  821. CFontInfo::SetMaxWidth
  822. This is not as simple as it might seem. If the font is variable, don't do
  823. it. If it is not, then if it is DBCS, set the average width to 1/2 the new
  824. maximum. Otherwise, set it also to the maximum.
  825. ******************************************************************************/
  826. void CFontInfo::SetMaxWidth(WORD wWidth)
  827. {
  828. if (IsVariableWidth()) return;
  829. if (wWidth == m_IFIMETRICS.fwdMaxCharInc) return; // Nothing to do!
  830. // if (wWidth == m_wMaximumIncrement) return; // Nothing to do!
  831. m_IFIMETRICS.fwdMaxCharInc = wWidth; // rm new
  832. // m_wMaximumIncrement = wWidth; // rm ori
  833. m_IFIMETRICS.fwdAveCharWidth = DBCSFont() ? (wWidth + 1) >> 1 : wWidth; // rm new
  834. // m_wAverageWidth = DBCSFont() ? (wWidth + 1) >> 1 : wWidth; // rm old
  835. Changed();
  836. }
  837. /*****************************************************************************
  838. CFontInfo::SetHeight
  839. This member checks to see if the new height is non-zero and new. If so, it
  840. uses it for the new height, then adjusts all of the possibly affected
  841. special metrics so they continue to meet the constraints.
  842. ******************************************************************************/
  843. BOOL CFontInfo::SetHeight(WORD wHeight)
  844. {
  845. if (!wHeight || wHeight == m_wHeight) return FALSE;
  846. m_wHeight = wHeight;
  847. // short sBaseline = (short) (min(wHeight, m _cwaSpecial[Baseline])); // rm ori
  848. short sBaseline = (short) (min(wHeight, m_IFIMETRICS.fwdWinAscender));
  849. for (unsigned u = 0; u <= InternalLeading; u++)
  850. {
  851. switch (u)
  852. {
  853. case InterlineGap:
  854. if (m_cwaSpecial[u] > 2 * wHeight) m_cwaSpecial[u] = 2 * wHeight;
  855. continue;
  856. case UnderOffset:
  857. case SubMoveY:
  858. case Lowerd:
  859. if ((short) m_cwaSpecial[u] < sBaseline - wHeight)
  860. m_cwaSpecial[u] = sBaseline - wHeight;
  861. continue;
  862. case UnderSize:
  863. if (m_cwaSpecial[u] > wHeight - (unsigned) sBaseline)
  864. m_cwaSpecial[u] = wHeight = (unsigned) sBaseline;
  865. if (!m_cwaSpecial[u]) m_cwaSpecial[u] = 1;
  866. continue;
  867. case SuperSizeX:
  868. case SubSizeX:
  869. case SuperMoveX:
  870. case SubMoveX:
  871. case ItalicAngle:
  872. continue; // These aren't affected
  873. default:
  874. if (m_cwaSpecial[u] > (unsigned) sBaseline)
  875. m_cwaSpecial[u] = sBaseline;
  876. }
  877. }
  878. // Adjust the scaling factors if need be
  879. if (m_wScaleDevice > m_wHeight - m_InternalLeading) //m _cwaSpecial[InternalLeading])
  880. m_wScaleDevice = m_wHeight - m_InternalLeading; //m _cwaSpecial[InternalLeading];
  881. if (m_wMinScale > m_wHeight - m_InternalLeading) //m _cwaSpecial[InternalLeading])
  882. m_wMinScale = m_wHeight - m_InternalLeading; //m _cwaSpecial[InternalLeading];
  883. Changed();
  884. return TRUE;
  885. }
  886. /*****************************************************************************
  887. CFontInfo::SetCharacterSet
  888. This one is a bit tricky- the new character set must be compatible with the
  889. GTT file associated with this font. So we need to check it before we pass
  890. on it.
  891. ASSUMPTIONS:
  892. (1) Things are bulletproof enough that the existing character set will
  893. already pass this test.
  894. ******************************************************************************/
  895. BOOL CFontInfo::SetCharacterSet(BYTE bNew) {
  896. unsigned u;
  897. switch (bNew) {
  898. case SHIFTJIS_CHARSET:
  899. for (u = 0; u < m_pcgmTranslation -> CodePages(); u++)
  900. if (m_pcgmTranslation -> PageID(u) == 932)
  901. break; // We're OK
  902. if (u == m_pcgmTranslation -> CodePages())
  903. return FALSE;
  904. break;
  905. case HANGEUL_CHARSET:
  906. for (u = 0; u < m_pcgmTranslation -> CodePages(); u++)
  907. if (m_pcgmTranslation -> PageID(u) == 949)
  908. break; // We're OK
  909. if (u == m_pcgmTranslation -> CodePages())
  910. return FALSE;
  911. break;
  912. case CHINESEBIG5_CHARSET:
  913. for (u = 0; u < m_pcgmTranslation -> CodePages(); u++)
  914. if (m_pcgmTranslation -> PageID(u) == 950)
  915. break; // We're OK
  916. if (u == m_pcgmTranslation -> CodePages())
  917. return FALSE;
  918. break;
  919. case GB2312_CHARSET:
  920. for (u = 0; u < m_pcgmTranslation -> CodePages(); u++)
  921. if (m_pcgmTranslation -> PageID(u) == 936)
  922. break; // We're OK
  923. if (u == m_pcgmTranslation -> CodePages())
  924. return FALSE;
  925. break;
  926. default:
  927. // Don't accept any DBCS codepages
  928. for (u = 0; u < m_pcgmTranslation -> CodePages(); u++)
  929. switch (m_pcgmTranslation -> PageID(u)) {
  930. case 932:
  931. case 936:
  932. case 949:
  933. case 950:
  934. case 1361: // Johab- but it isn't in the converter!
  935. return FALSE;
  936. }
  937. }
  938. // if (m_bCharacterSet != bNew) { // rm - need to replace this functionality
  939. // m_bCharacterSet = bNew;
  940. Changed();
  941. // }
  942. return TRUE;
  943. }
  944. /******************************************************************************
  945. CFontInfo::SetSignificant
  946. This member is called to change the value of one of the significant code
  947. points (break character or default) encoded in the font. Doing this
  948. correctly means getting the ANSI and UNICODE versions of the code point, and
  949. discarding any out-of-range values.
  950. This function returns an encoded value indicating success or cause of
  951. failure.
  952. ******************************************************************************/
  953. WORD CFontInfo::SetSignificant(WORD wItem, WORD wChar, BOOL bUnicode)
  954. {
  955. // _ASSERT(wItem > Last && wItem <= Break); // rm no longer needed
  956. if (!bUnicode && wChar > 255) return DoubleByte;
  957. CWaitCursor cwc; // Unfortunately, if not Unicode, this is slow
  958. CPtrArray cpaGlyphs;
  959. CWordArray cwa;
  960. CByteArray cba;
  961. CDWordArray cdaPage;
  962. m_pcgmTranslation -> Collect(cpaGlyphs);
  963. m_pcgmTranslation -> CodePages(cdaPage);
  964. for (int i = 0; i < cpaGlyphs.GetSize(); i++)
  965. {
  966. CGlyphHandle& cgh = *(CGlyphHandle *) cpaGlyphs[i];
  967. if (bUnicode)
  968. {
  969. if (cgh.CodePoint() == wChar)
  970. {
  971. cwa.Add(wChar);
  972. pccpi->Convert(cba, cwa, cdaPage[cgh.CodePage()]);
  973. break;
  974. }
  975. }
  976. else
  977. {
  978. if (i)
  979. cwa.SetAt(0, cgh.CodePoint());
  980. else
  981. cwa.Add(cgh.CodePoint());
  982. pccpi->Convert(cba, cwa, cdaPage[cgh.CodePage()]);
  983. if (cba.GetSize() == 1 && cba[0] == (BYTE) wChar)
  984. break;
  985. cba.RemoveAll(); // So we can try again
  986. }
  987. }
  988. if (i == cpaGlyphs.GetSize()) return InvalidChar;
  989. if (cba.GetSize() != 1) return DoubleByte;
  990. // OK, we passed all of the hurdles
  991. // if (m_cwaSignificant[wItem] == cwa[0]) return OK; // Nothing changed!!!! // rm ori - no longer needed, incorporated below
  992. if (wItem == Default)
  993. {
  994. if (m_IFIMETRICS.wcDefaultChar == cwa[0]) return OK; // Nothing changed!!!!
  995. m_IFIMETRICS.wcDefaultChar = cwa[0];
  996. m_IFIMETRICS.chDefaultChar = cba[0];
  997. }
  998. else
  999. {
  1000. m_IFIMETRICS.wcBreakChar = cwa[0];
  1001. m_IFIMETRICS.chBreakChar = cba[0];
  1002. }
  1003. // m_cwaSignificant[wItem] = cwa[0]; // rm ori no longer needed
  1004. // m_cbaSignificant[wItem] = cba[0]; // rm ori no longer needed
  1005. Changed();
  1006. return OK;
  1007. }
  1008. /******************************************************************************
  1009. CFontInfo::SetScaleLimit
  1010. This member receives a proposed new maximum or minimum font size in device
  1011. units. First, it is compared to the existing size, for a quick exit. Then
  1012. we check to see that the ordering of the limits and the nominal size is
  1013. preserved. If it is not, we describe the problem and leave. Otherwise, we
  1014. update the value, and note that the font information has changed.
  1015. ******************************************************************************/
  1016. WORD CFontInfo::SetScaleLimit(BOOL bMax, WORD wNew) {
  1017. if (wNew == (bMax ? m_wMaxScale : m_wMinScale))
  1018. return ScaleOK;
  1019. if (bMax ? wNew <= m_wMinScale : wNew >= m_wMaxScale)
  1020. return Reversed;
  1021. if (bMax ? wNew < m_wScaleDevice : wNew > m_wScaleDevice)
  1022. return NotWindowed;
  1023. if (bMax)
  1024. m_wMaxScale = wNew;
  1025. else
  1026. m_wMinScale = wNew;
  1027. Changed();
  1028. return ScaleOK;
  1029. }
  1030. /******************************************************************************
  1031. CFontInfo::SetDeviceEmHeight
  1032. This member sets the units used for determing the conversion from font units
  1033. (in which all metrics are given) to device units. The checking is similar to
  1034. that above, except here, we need to make sure that the font units are always
  1035. of equal or greater resolution than the device units.
  1036. ******************************************************************************/
  1037. WORD CFontInfo::SetDeviceEmHeight(WORD wNew)
  1038. {
  1039. if (wNew == m_wScaleDevice)
  1040. return ScaleOK;
  1041. if (wNew > m_wHeight - m_InternalLeading) //m _cwaSpecial[InternalLeading])
  1042. return Reversed;
  1043. if (wNew < m_wMinScale || wNew > m_wMaxScale)
  1044. return NotWindowed;
  1045. m_wScaleDevice = wNew;
  1046. Changed();
  1047. return ScaleOK;
  1048. }
  1049. /******************************************************************************
  1050. CFontInfo::Load
  1051. This member function loads the UFM file, finally initializing all of the
  1052. tons of individual values we're trying to pretend we know how to manage
  1053. here.
  1054. IA64 : 1. conversion change loXXX in UNIFI_HDR to 8 byte aligned
  1055. 2. this part also changed accordingly
  1056. 3. what if we load 32 bit UFM(not conversion in new source) in IA64?
  1057. ->1. Need to new converstion tool from UFM32 to UFM64
  1058. ->2. this tool Can't be embedded in MDT because this take some time
  1059. (loading ->checking -> storing after that structure on every loXXX)
  1060. ******************************************************************************/
  1061. BOOL CFontInfo::Load(bool bloadedbyworkspace /*= false*/)
  1062. {
  1063. // Save the load location flag.
  1064. m_bLoadedByWorkspace = bloadedbyworkspace ;
  1065. // Prepare to open the file.
  1066. CFile cfUFM;
  1067. char pszFullName[128] = "";
  1068. if (!SUCCEEDED(StringCchCopyA(pszFullName, CCHOF(pszFullName), (const char *) m_cfn.FullName())))
  1069. {
  1070. throw;
  1071. }
  1072. // Open the UFM file
  1073. if (!cfUFM.Open(m_cfn.FullName(), CFile::modeRead | CFile::shareDenyWrite)) {
  1074. CString csMessage;
  1075. csMessage.Format(IDS_LoadFailure, (LPCTSTR) m_cfn.FullName());
  1076. AfxMessageBox(csMessage);
  1077. return FALSE;
  1078. }
  1079. // Get the length of the UFM file. If it is too short to be correctly
  1080. // formed, complain and return FALSE; ie, load failure.
  1081. int i = cfUFM.GetLength() ;
  1082. if (i < sizeof(UNIFM_HDR)) {
  1083. CString csmsg ;
  1084. csmsg.Format(IDS_UFMTooSmallError, m_cfn.NameExt()) ;
  1085. AfxMessageBox(csmsg, MB_ICONEXCLAMATION) ;
  1086. return FALSE ;
  1087. } ;
  1088. CByteArray cbaUFM; // Loaded with file's contents
  1089. // Try to load the file- proclaim defeat on any exception.
  1090. try {
  1091. cbaUFM.SetSize(i);
  1092. cfUFM.Read(cbaUFM.GetData(), (unsigned)cbaUFM.GetSize());
  1093. }
  1094. catch (CException *pce) {
  1095. pce -> ReportError();
  1096. pce -> Delete();
  1097. CString csMessage;
  1098. csMessage.Format(IDS_LoadFailure, (LPCTSTR) m_cfn.FullName());
  1099. AfxMessageBox(csMessage);
  1100. return FALSE;
  1101. }
  1102. //------------------------------------------------------------------------------------------------------------------------------------------
  1103. PUNIFM_HDR pufmh = (PUNIFM_HDR) cbaUFM.GetData(); // UNIFM_HDR
  1104. m_ulDefaultCodepage = (WORD) pufmh -> ulDefaultCodepage;
  1105. m_lGlyphSetDataRCID = (WORD) pufmh -> lGlyphSetDataRCID; // Store the GTT ID
  1106. //------------------------------------------------------------------------------------------------------------------------------------------
  1107. union { //raid 154639
  1108. PBYTE pbudi;
  1109. PUNIDRVINFO pudi;
  1110. };
  1111. pudi = (PUNIDRVINFO) (cbaUFM.GetData() + pufmh->loUnidrvInfo); // UNIDRVINFO
  1112. if (!pudi -> dwSize || !pudi -> wXRes || !pudi -> wYRes) //raid 154639
  1113. pbudi +=4; // normally converion from 32 bit OS.
  1114. memcpy((void *) &m_UNIDRVINFO, pudi, sizeof(UNIDRVINFO)); // Bulk copy everything
  1115. if (pudi -> SelectFont.loOffset) // Fill in the two invocation strings - why it is
  1116. m_ciSelect.Init((PBYTE) pudi + pudi->SelectFont.loOffset, // the offset is NULL and the count is garbage
  1117. pudi->SelectFont.dwCount); // when there is none is beyond me, but so be it.
  1118. if (pudi->UnSelectFont.loOffset)
  1119. m_ciDeselect.Init((PBYTE) pudi + pudi->UnSelectFont.loOffset,
  1120. pudi->UnSelectFont.dwCount);
  1121. //------------------------------------------------------------------------------------------------------------------------------------------
  1122. // IFIMETRICS
  1123. union {
  1124. PBYTE pbIFI;
  1125. PIFIMETRICS pIFI;
  1126. };
  1127. pbIFI = cbaUFM.GetData() + pufmh->loIFIMetrics; // Assign byte pointer to file IFIMETRICS data
  1128. if (!pIFI -> cjThis || !pIFI ->chLastChar) //raid 154639
  1129. pbIFI +=4;
  1130. memcpy((void *) &m_IFIMETRICS, pIFI, sizeof(IFIMETRICS) ); // Bulk copy everything
  1131. if ( !(m_IFIMETRICS.fsSelection & FM_SEL_REGULAR) // If font isn't defined as regular, or bold,
  1132. && !(m_IFIMETRICS.fsSelection & FM_SEL_BOLD) ) // then just set it to regular.
  1133. m_IFIMETRICS.fsSelection |= FM_SEL_REGULAR;
  1134. //-----------------------------------------------------
  1135. m_csUnique = (PWSTR) (pbIFI + pIFI->dpwszUniqueName); // dpwszUniqueName
  1136. m_csStyle = (PWSTR) (pbIFI + pIFI->dpwszStyleName); // dpwszStyleName
  1137. m_csFace = (PWSTR) (pbIFI + pIFI->dpwszFaceName); // dpwszFaceName
  1138. //-----------------------------------------------------
  1139. m_csaFamily.RemoveAll(); // Just in case it isn't clean
  1140. PWSTR pwstrFamily = (PWSTR) (pbIFI + pIFI->dpwszFamilyName); // dpwszFamilyName
  1141. CString csWork(pwstrFamily); // Let CString handle the Unicode conversions for us,
  1142. m_csaFamily.Add(csWork);
  1143. pwstrFamily += 1 + wcslen(pwstrFamily);
  1144. if (pIFI->flInfo & FM_INFO_FAMILY_EQUIV)
  1145. while (*pwstrFamily)
  1146. {
  1147. csWork = pwstrFamily;
  1148. m_csaFamily.Add(csWork);
  1149. pwstrFamily += 1 + wcslen(pwstrFamily);
  1150. }
  1151. //-----------------------------------------------------
  1152. m_ItalicAngle = (WORD) (gdConvertRadToDegree * // m_ItalicAngle
  1153. atan2((double) pIFI->ptlCaret.x, (double) pIFI->ptlCaret.y));
  1154. m_wHeight = m_IFIMETRICS.fwdWinAscender + m_IFIMETRICS.fwdWinDescender; // m_wHeight // rm new
  1155. m_InternalLeading = m_wHeight - m_IFIMETRICS.fwdUnitsPerEm; // fwdUnitsPerEm // rm new
  1156. //------------------------------------------------------------------------------------------------------------------------------------------
  1157. // Try to find and load the GTT referenced by this UFM iff this UFM is being
  1158. // loaded directly.
  1159. if (!m_bLoadedByWorkspace)
  1160. if (!FindAndLoadGTT()) {
  1161. CString csmsg;
  1162. csmsg.Format(IDS_NoGTTForUFMFatalError, m_cfn.NameExt()) ;
  1163. AfxMessageBox(csmsg, MB_ICONEXCLAMATION) ;
  1164. return FALSE ;
  1165. } ;
  1166. // DEAD_BUG: This is a good place to add code to find and associate the UFM
  1167. // with its GTT so that the UFM doesn't have to be loaded twice
  1168. // when the UFM is loaded as part of a workspace load.
  1169. //
  1170. // best solution is just skipping EXTTEXTMETRIC, but almost no influence.
  1171. //------------------------------------------------------------------------------------------------------------------------------------------
  1172. if ( !m_pcgmTranslation && m_bLoadedByWorkspace )
  1173. return FALSE;
  1174. // EXTTEXTMETRIC
  1175. for (i = 0; i < 26; i++) // Preload zeroes into the m_EXTTEXTMETRIC structure.
  1176. *(SHORT *)((SHORT *)&m_EXTTEXTMETRIC + i) = 0;
  1177. //raid 154639
  1178. union {
  1179. PBYTE pbetm;
  1180. PEXTTEXTMETRIC petm;
  1181. };
  1182. petm = (PEXTTEXTMETRIC) (pufmh->loExtTextMetric ? // Get pointer - if EXTTEXTMETRIC data exists
  1183. (cbaUFM.GetData() + pufmh->loExtTextMetric) : NULL);
  1184. if (petm)
  1185. {
  1186. if (!petm -> emSize || !petm -> emPointSize)
  1187. pbetm += 4;
  1188. m_fSave_EXT = TRUE;
  1189. m_fEXTTEXTMETRIC = TRUE;
  1190. memcpy((void *) &m_EXTTEXTMETRIC, petm, sizeof(EXTTEXTMETRIC) ); // Bulk copy everything
  1191. m_wMinScale = m_EXTTEXTMETRIC.emMinScale;
  1192. m_wMaxScale = m_EXTTEXTMETRIC.emMaxScale;
  1193. m_Lowerd = m_EXTTEXTMETRIC.emLowerCaseAscent;
  1194. m_Lowerp = m_EXTTEXTMETRIC.emLowerCaseDescent;
  1195. m_ItalicAngle = m_EXTTEXTMETRIC.emSlant;
  1196. // m_bfScaleOrientation = (BYTE) m_EXTTEXTMETRIC.emOrientation;
  1197. m_wScaleDevice = m_EXTTEXTMETRIC.emMasterHeight;
  1198. }
  1199. //------------------------------------------------------------------------------------------------------------------------------------------
  1200. if (pIFI->dpFontSim) // FONTSIM, if any.
  1201. {
  1202. union {
  1203. PBYTE pbfs;
  1204. FONTSIM *pfs;
  1205. };
  1206. pbfs = pbIFI + pIFI -> dpFontSim;
  1207. if (m_pcfdBold) delete m_pcfdBold; // If we're reloading, clean these up!
  1208. if (m_pcfdItalic) delete m_pcfdItalic;
  1209. if (m_pcfdBoth) delete m_pcfdBoth;
  1210. if (pfs->dpBold) m_pcfdBold = new CFontDifference(pbfs + pfs->dpBold, this); // Bold simulation
  1211. if (pfs->dpItalic) m_pcfdItalic = new CFontDifference(pbfs + pfs->dpItalic, this); // Italic Simulation
  1212. if (pfs->dpBoldItalic) m_pcfdBoth = new CFontDifference(pbfs + pfs->dpBoldItalic, this); // Bold Italic Simulation
  1213. }
  1214. //------------------------------------------------------------------------------------------------------------------------------------------
  1215. //if (m_pcgmTranslation && (m_loWidthTable = pufmh -> loWidthTable)) // WIDTH TABLE, but only if there is an associated GTT.
  1216. if (m_pcgmTranslation && pufmh->loWidthTable ) //pufmh->loWidthTable) // WIDTH TABLE, but only if there is an associated GTT.
  1217. {
  1218. union {
  1219. PBYTE pbwt;
  1220. PWIDTHTABLE pwt;
  1221. };
  1222. pbwt = cbaUFM.GetData() + pufmh -> loWidthTable;
  1223. // dwSize has problem ; there are case: dwAdd_ in pfm2ifi has not 4 byte, so dwSize has number in some case
  1224. // data before wGlyphCount is dwRunNum: impossible to beyond ff ff 00 00 (65536), as long as dwAdd is 4,2 not 1 & dwRun > 256
  1225. // nicer solution is required : BUG_BUG.
  1226. if( !pwt ->dwSize || !pwt ->WidthRun ->wGlyphCount)
  1227. pbwt += 4;
  1228. m_pcgmTranslation -> Collect(m_cpaGlyphs); // Collect all the handles
  1229. m_pcgmTranslation -> Collect(m_cpaOldGlyphs); //244123
  1230. //244123 // when delete glyph, memory is occupied with dddd, so we have to save original data in here
  1231. m_cwaOldGlyphs.SetSize(m_cpaOldGlyphs.GetSize()) ;
  1232. for ( i = 0 ; i < m_cpaOldGlyphs.GetSize() ; i ++ ) {
  1233. CGlyphHandle& cghThis = *(CGlyphHandle *) m_cpaOldGlyphs[i];
  1234. m_cwaOldGlyphs.SetAt(i,cghThis.CodePoint() ) ;
  1235. }
  1236. m_cwaWidth.RemoveAll();
  1237. if (m_cpaGlyphs.GetSize() > 0)
  1238. m_cwaWidth.InsertAt(0, 0, m_cpaGlyphs.GetSize());
  1239. unsigned uWidth = (unsigned)m_cwaWidth.GetSize(); // rm fix VC compiler problem?
  1240. unsigned uWidthIdx ;
  1241. for (unsigned u = 0; u < pwt->dwRunNum; u++)
  1242. {
  1243. PWORD pwWidth = (PWORD) (pbwt + pwt->WidthRun[u].loCharWidthOffset);
  1244. for (unsigned uGlyph = 0; uGlyph < pwt->WidthRun[u].wGlyphCount; uGlyph++)
  1245. {
  1246. // For whatever reason, there are times when the index value is
  1247. // < 0 or > uWidth. An AV would occur if m_cwaWidth were allowed
  1248. // to be indexed by such a value. Just keep this from happening
  1249. // for now. A better fix is needed. BUG_BUG : won't fix
  1250. uWidthIdx = uGlyph + -1 + pwt->WidthRun[u].wStartGlyph ; // Glyph handles start at 1, not 0!
  1251. if ((int) uWidthIdx < 0) {
  1252. //AfxMessageBox("Negative width table index") ;
  1253. //TRACE("***Negative width table index (%d) found in %s. Table size=%d uGlyph=%d wGlyphCount=%d wStartGlyph=%d u=%d dwRunNum=%d\n", uWidthIdx, Name(), uWidth, uGlyph, pwt->WidthRun[u].wGlyphCount, pwt->WidthRun[u].wStartGlyph, u, pwt->dwRunNum) ;
  1254. continue ;
  1255. } else if (uWidthIdx >= uWidth) {
  1256. //AfxMessageBox("Width table index (%d) > table size") ;
  1257. //TRACE("***Width table index (%d) > table size (%d) found in %s. Table size=%d uGlyph=%d wGlyphCount=%d wStartGlyph=%d u=%d dwRunNum=%d\n", uWidthIdx, uWidth, Name(), uWidth, uGlyph, pwt->WidthRun[u].wGlyphCount, pwt->WidthRun[u].wStartGlyph, u, pwt->dwRunNum) ;
  1258. break ; // rm fix VC IDE compiler problem?
  1259. } ;
  1260. //m_cwaWidth[uGlyph + -1 + pwt->WidthRun[u].wStartGlyph] = *pwWidth++; // Glyph handles start at 1, not 0!
  1261. m_cwaWidth[uWidthIdx] = *pwWidth++;
  1262. }
  1263. }
  1264. }
  1265. //------------------------------------------------------------------------------------------------------------------------------------------
  1266. m_csoaKern.RemoveAll(); // KERNING TABLE, if any
  1267. if (pufmh -> loKernPair)
  1268. {
  1269. union {
  1270. PBYTE pbkd;
  1271. PKERNDATA pkd;
  1272. };
  1273. pkd = (PKERNDATA) (cbaUFM.GetData() + pufmh -> loKernPair);
  1274. if (!pkd ->dwSize || !pkd->KernPair ->wcSecond || !pkd->KernPair ->wcFirst)
  1275. pbkd += 4;
  1276. unsigned rm = pkd->dwKernPairNum; // rm - debugging
  1277. for (unsigned u = 0; u < pkd -> dwKernPairNum; u++)
  1278. m_csoaKern.Add(new CKern(pkd -> KernPair[u]));
  1279. }
  1280. //------------------------------------------------------------------------------------------------------------------------------------------
  1281. return TRUE; // Return triumphant to whoever deigned to need this service.
  1282. }
  1283. /*****************************************************************************
  1284. CFontInfo::FindAndLoadGTT
  1285. This function is called when a UFM is being loaded directly. Its job is to
  1286. find the associated GTT, load it, and set the UFM's pointer to this GTT. If
  1287. this fails, the user is told that no changes to this UFM can be saved if he
  1288. decides to continue loading it.
  1289. True is returned if a GTT was found and loaded. Return false if the GTT
  1290. wasn't loaded and the user doesn't want to continue to load the UFM.
  1291. ******************************************************************************/
  1292. bool CFontInfo::FindAndLoadGTT()
  1293. {
  1294. // Load a predefined GTT/codepage if that is what is referenced by the UFM.
  1295. CGlyphMap* pcgm ;
  1296. pcgm = CGlyphMap::Public((WORD)Translation(), (WORD) m_ulDefaultCodepage, 0,
  1297. GetFirst(), GetLast()) ;
  1298. if (pcgm) {
  1299. SetTranslation(pcgm) ;
  1300. m_pcgmTranslation->NoteOwner(*m_pcdOwner) ; // Is this right/necessary?
  1301. m_bLoadedByWorkspace = true ;
  1302. return true ;
  1303. } ;
  1304. // Looks like no easy way out. Now I need to try to find and read the
  1305. // corresponding RC file so that it can be read to find a filespec for this
  1306. // UFM's GTT. First, build a file spec for the RC file. Assume it is in
  1307. // the directory above the one containing this UFM.
  1308. CString csrcfspec(FilePath()) ;
  1309. if (csrcfspec.GetLength() > 3)
  1310. csrcfspec = csrcfspec.Left(csrcfspec.GetLength() - 1) ;
  1311. csrcfspec = csrcfspec.Left(csrcfspec.ReverseFind(_T('\\')) + 1) ;
  1312. CString csrcpath(csrcfspec.Left(csrcfspec.GetLength() - 1)) ;
  1313. csrcfspec += _T("*.rc") ;
  1314. // I don't know the name of the RC file so look for it in the specified
  1315. // directory. Assume that the file is the first RC file in the directory
  1316. // that is NOT called "common.rc".
  1317. CFileFind cff ;
  1318. CString cstmp ;
  1319. BOOL bfound = cff.FindFile(csrcfspec) ;
  1320. bool breallyfound = false ;
  1321. while (bfound) {
  1322. bfound = cff.FindNextFile() ;
  1323. cstmp = cff.GetFileTitle() ;
  1324. cstmp.MakeLower() ;
  1325. if (cstmp != _T("common")) {
  1326. csrcfspec = cff.GetFilePath() ;
  1327. breallyfound = true ;
  1328. break ;
  1329. } ;
  1330. } ;
  1331. // Prepare to ask the user what to do if any of the next few steps fail.
  1332. CString csnext ;
  1333. csnext.Format(IDS_StandAloneFontLoad, m_cfn.NameExt()) ;
  1334. // If the RC file is not found, ...
  1335. if (!breallyfound) {
  1336. // ...Ask the user if he wants to tell us where it is. If he says no,
  1337. // ask if he want to stop or open it restricted.
  1338. cstmp.Format(IDS_RCForUFMPrompt, m_cfn.NameExt()) ;
  1339. if (AfxMessageBox(cstmp, MB_YESNO+MB_ICONQUESTION) == IDNO)
  1340. return (AfxMessageBox(csnext, MB_YESNO+MB_ICONQUESTION) == IDYES) ;
  1341. // Prompt the use for the path to the RC file. If he cancels, ask if
  1342. // he want to stop or open it restricted.
  1343. // Prompt the user for a new RC file. If the operation is canceled,
  1344. // ask if he wants to stop or open it restricted.
  1345. cstmp.LoadString(IDS_CommonRCFile) ;
  1346. CFileDialog cfd(TRUE, _T(".RC"), NULL,
  1347. OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, cstmp) ;
  1348. cfd.m_ofn.lpstrInitialDir = csrcpath ;
  1349. if (cfd.DoModal() != IDOK)
  1350. return (AfxMessageBox(csnext, MB_YESNO+MB_ICONQUESTION) == IDYES) ;
  1351. // Prepare to check the new filespec
  1352. csrcfspec = cfd.GetPathName() ;
  1353. csrcpath = csrcfspec.Left(csrcfspec.ReverseFind(_T('\\'))) ;
  1354. } ;
  1355. // I've got an RC filespec now so try to open it and read its contents.
  1356. // If the operation fails, ask if he wants to stop or open it restricted.
  1357. CStringArray csarclines ;
  1358. if (!LoadFile(csrcfspec, csarclines))
  1359. return (AfxMessageBox(csnext, MB_YESNO+MB_ICONQUESTION) == IDYES) ;
  1360. // Now try to find the line in the RC file that contains the ID for this
  1361. // UFM's GTT. If the operation fails, ask if he wants to stop or open it
  1362. // restricted.
  1363. for (int n = 0 ; n < csarclines.GetSize() ; n++) {
  1364. if (csarclines[n].Find(_T("RC_GTT")) == -1)
  1365. continue ;
  1366. if (atoi(csarclines[n]) == Translation())
  1367. break ;
  1368. } ;
  1369. if (n >= csarclines.GetSize())
  1370. return (AfxMessageBox(csnext, MB_YESNO+MB_ICONQUESTION) == IDYES) ;
  1371. // The GTT filespec in the RC file should be relative to the location of
  1372. // the RC file. So, combine the filespec with the RC file path to get
  1373. // the complete filespec for the GTT file.
  1374. CString csgttfspec ;
  1375. int nloc = csarclines[n].ReverseFind(_T(' ')) ;
  1376. csgttfspec = csarclines[n].Right(csarclines[n].GetLength() - nloc - 1) ;
  1377. csgttfspec = csrcpath + _T("\\") + csgttfspec ;
  1378. // Allocate a new Glyph class instance, initialize it, and load it. If the
  1379. // operations fails, ask if the user wants to stop or open it restricted.
  1380. pcgm = new CGlyphMap ;
  1381. pcgm->nSetRCID((int) Translation()) ;
  1382. pcgm->NoteOwner(*m_pcdOwner) ; // Is this right/necessary?
  1383. if (!pcgm->Load(csgttfspec))
  1384. return (AfxMessageBox(csnext, MB_YESNO+MB_ICONQUESTION) == IDYES) ;
  1385. // The GTT has been loaded so set the UFM's GTT pointer variable, set
  1386. // m_bLoadedByWorkspace since everything has been fixed up as if it had
  1387. // been loaded from a workspace, and return true to indicate success.
  1388. SetTranslation(pcgm) ;
  1389. m_bLoadedByWorkspace = true ;
  1390. return true ;
  1391. }
  1392. /*****************************************************************************
  1393. CUniString class
  1394. This is a little helper class that will convert a CString to a UNICODE
  1395. string, and take care of cleanup, etc., so the font storage code doesn't get
  1396. any messier than it already will be.
  1397. ******************************************************************************/
  1398. class CUniString : public CWordArray
  1399. {
  1400. public:
  1401. CUniString(LPCSTR lpstrInit);
  1402. operator PCWSTR() const { return GetData(); }
  1403. unsigned GetSize() const { return sizeof (WCHAR) * (unsigned) CWordArray::GetSize(); }
  1404. void Write(CFile& cf) { cf.Write(GetData(), GetSize()); }
  1405. };
  1406. CUniString::CUniString(LPCSTR lpstrInit)
  1407. {
  1408. SetSize(MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpstrInit, -1, NULL, 0));
  1409. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpstrInit, -1, GetData(), GetSize());
  1410. }
  1411. /*****************************************************************************
  1412. CFontInfo::Store
  1413. This member function stores the UFM format information in the specified file
  1414. by assembling it from the information we have cached in this class.
  1415. // typedef struct _UNIDRVINFO
  1416. // {
  1417. // DWORD dwSize; // Size of this structure
  1418. // DWORD flGenFlags; // General flags
  1419. // WORD wType; // Type of the font like CAPSL
  1420. // WORD fCaps; // Font Capability flags
  1421. // WORD wXRes; // Horizontal resolution of the font
  1422. // WORD wYRes; // Vertical Resolution of the font
  1423. // short sYAdjust; // Vertical Cursor position Adjustment
  1424. // short sYMoved; // Adjustment to Y position after printing
  1425. // WORD wPrivateData; // For backward compatibility, don't show in UI.
  1426. // short sShift; // For backward compatibility, don't show in UI.
  1427. // INVOCATION SelectFont;
  1428. // INVOCATION UnSelectFont;
  1429. // WORD wReserved[4];
  1430. // } UNIDRVINFO, *PUNIDRVINFO;
  1431. //
  1432. //
  1433. // And now, ladies and gentlemen, direct from the pages of WINDDI.H,
  1434. // I present to you:
  1435. //
  1436. // "rather than adding the fields of IFIEXTRA to IFIMETRICS itself
  1437. // we add them as a separate structure. This structure, if present at all,
  1438. // lies below IFIMETRICS in memory.
  1439. // If IFIEXTRA is present at all, ifi.cjIfiExtra (formerly ulVersion)
  1440. // will contain size of IFIEXTRA including any reserved fields.
  1441. // That way ulVersion = 0 (NT 3.51 or less) printer minidrivers
  1442. // will work with NT 4.0."
  1443. //
  1444. // typedef struct _IFIEXTRA
  1445. // {
  1446. // ULONG ulIdentifier; // used for Type 1 fonts only
  1447. // PTRDIFF dpFontSig; // nontrivial for tt only, at least for now.
  1448. // ULONG cig; // maxp->numGlyphs, # of distinct glyph indicies
  1449. // PTRDIFF dpDesignVector; // offset to design vector for mm instances
  1450. // PTRDIFF dpAxesInfoW; // offset to full axes info for base mm font
  1451. // ULONG aulReserved[1]; // in case we need even more stuff in the future
  1452. // } IFIEXTRA, *PIFIEXTRA;
  1453. //
  1454. ******************************************************************************/
  1455. BOOL CFontInfo::Store(LPCTSTR lpstrFile, BOOL bStoreFormWokspace)
  1456. {
  1457. // Fonts loaded standalone cannot be saved because m_pcgmTranslation is not
  1458. // set. Tell the user and exit. TRUE is returned to keep this from
  1459. // happening again.
  1460. if (!m_bLoadedByWorkspace) {
  1461. CString csmsg ;
  1462. csmsg.LoadString(IDS_CantStoreStandAlone) ;
  1463. AfxMessageBox(csmsg) ;
  1464. return TRUE ;
  1465. } ;
  1466. DWORD dwAdd_UniDrv = 0;
  1467. DWORD dwAdd_IFI = 0;
  1468. DWORD dwAdd_ExtTextM = 0;
  1469. DWORD dwAdd_WidthTable = 0;
  1470. DWORD dwAdd_KerPair = 0;
  1471. // DWORD dwAdd_SelectedFont;
  1472. // DWORD dwAdd_UnSelectedFont;
  1473. static const BYTE InsertZero[8] = {0,0,0,0,0,0,0,0};
  1474. const short OS_BYTE = 0x08;
  1475. // If a UFM loaded from a workspace can't be saved normally because it did
  1476. // not have a valid GTT/CP, call another routine to handle this case and
  1477. // return whatever it returns.
  1478. if (m_bWSLoadButNoGTTCP)
  1479. return StoreGTTCPOnly(lpstrFile) ;
  1480. try { // Any exxceptions, we'll just fail gracelessly
  1481. CFile cfUFM(lpstrFile, // Create/open the output file.
  1482. CFile::modeCreate | CFile::modeWrite | CFile::shareExclusive);
  1483. //------------------------------------------------------------------------------------------------------------------------------------------
  1484. // UNIFM_HDR
  1485. UNIFM_HDR ufmh = {sizeof ufmh, UNIFM_VERSION_1_0, 0, // Create the output UNIFM_HDR
  1486. (short) m_lGlyphSetDataRCID, sizeof ufmh}; // rm new
  1487. // int q = m_pcgmTranslation -> m_csoaCodePage.GetSize(); // rm test
  1488. // int r = m_pcgmTranslation -> CodePages(); // rm test
  1489. // ufmh.ulDefaultCodepage = m_pcgmTranslation -> CodePage(0).Page(); // rm test
  1490. // Previously, the default code page in the UFM's GTT was always saved.
  1491. // This ignored the user's changes in the UFM editor. Now, the user's
  1492. // choice is saved if it is valid (other checking done in other places).
  1493. // Otherwise, the GTT's default code page is used when there is a GTT
  1494. // associated with the UFM. If not, assert.
  1495. if (m_ulDefaultCodepage > 0)
  1496. ufmh.ulDefaultCodepage = m_ulDefaultCodepage ;
  1497. else if (m_pcgmTranslation)
  1498. ufmh.ulDefaultCodepage = m_pcgmTranslation->DefaultCodePage() ;
  1499. else
  1500. ASSERT(0) ;
  1501. //ufmh.ulDefaultCodepage = m_pcgmTranslation -> DefaultCodePage(); // Use Glyph Map default code page if at all possible.
  1502. memset((PBYTE) ufmh.dwReserved, 0, sizeof ufmh.dwReserved); // Zero fill reserved bytes.
  1503. //------------------------------------------------------------------------------------------------------------------------------------------
  1504. ufmh.loUnidrvInfo = ufmh.dwSize; // UNIDRVINFO
  1505. if (dwAdd_UniDrv = ufmh.loUnidrvInfo & 0x07) {
  1506. dwAdd_UniDrv = OS_BYTE - dwAdd_UniDrv;
  1507. ufmh.loUnidrvInfo += dwAdd_UniDrv;
  1508. }
  1509. m_UNIDRVINFO.dwSize = sizeof (UNIDRVINFO);
  1510. m_UNIDRVINFO.SelectFont.loOffset = m_ciSelect.Length() ? m_UNIDRVINFO.dwSize : 0; // Invocation Strings affect the size,
  1511. /* if (dwAdd_SelectedFont = m_UNIDRVINFO.SelectFont.loOffset & 0x07) {
  1512. dwAdd_SelectedFont += OS_BYTE - dwAdd_SelectedFont;
  1513. m_UNIDRVINFO.SelectFont.loOffset += dwAdd_SelectedFont;
  1514. } */
  1515. m_UNIDRVINFO.dwSize += m_UNIDRVINFO.SelectFont.dwCount = m_ciSelect.Length(); // so get their specifics and
  1516. m_UNIDRVINFO.UnSelectFont.loOffset = m_ciDeselect.Length() ? m_UNIDRVINFO.dwSize : 0; // store them, updating the affected
  1517. /* if (dwAdd_UnSelectedFont = m_UNIDRVINFO.UnSelectFont.loOffset & 0x07) {
  1518. dwAdd_UnSelectedFont += OS_BYTE - dwAdd_UnSelectedFont;
  1519. ufmh.loUnidrvInfo += dwAdd_UnSelectedFont;
  1520. } */
  1521. m_UNIDRVINFO.dwSize += m_UNIDRVINFO.UnSelectFont.dwCount = m_ciDeselect.Length(); // size fields as we go.
  1522. unsigned uAdjustUDI = (4 - (m_UNIDRVINFO.dwSize % 4)) % 4; // you can delte this // Pad this to keep everything
  1523. // DWORD aligned in the file image!
  1524. ufmh.loIFIMetrics = ufmh.dwSize += m_UNIDRVINFO.dwSize += uAdjustUDI + dwAdd_UniDrv; // Store IFIMETRICS offset
  1525. if (dwAdd_IFI = ufmh.loIFIMetrics & 0x07) {
  1526. dwAdd_IFI = OS_BYTE - dwAdd_IFI;
  1527. ufmh.loIFIMetrics += dwAdd_IFI;
  1528. }
  1529. memset((PSTR) m_UNIDRVINFO.wReserved, 0, sizeof m_UNIDRVINFO.wReserved); // zero out reserved section.
  1530. //------------------------------------------------------------------------------------------------------------------------------------------
  1531. IFIEXTRA ifie = {0, 0, m_pcgmTranslation->Glyphs(), 0, 0, 0}; // Create the IFIEXTRA structure.
  1532. //------------------------------------------------------------------------------------------------------------------------------------------
  1533. // IFIMETRICS
  1534. IFIMETRICS ifi = {sizeof ifi + sizeof ifie, sizeof ifie}; // Create the output IFIMETRICS structure, being sure to add
  1535. // in the size of the IFIMETRICS structure, as well as the
  1536. // size of the IFIEXTRA structure.
  1537. // int iSizeOf_IFIMETRICS = sizeof(IFIMETRICS);
  1538. // memcpy((void *) &ifi, (void *) &m_IFIMETRICS, iSizeOf_IFIMETRICS ); // IFIMETRICS structure
  1539. // Store the IFIMETRICS data
  1540. ifi.lEmbedId = ifi.lItalicAngle = ifi.lCharBias = 0; //
  1541. ifi.dpCharSets = 0; // dpCharSets = 0 for now
  1542. ifi.jWinCharSet = m_IFIMETRICS.jWinCharSet; // jWinCharSet // rm new
  1543. ifi.jWinPitchAndFamily = m_IFIMETRICS.jWinPitchAndFamily; // jWinPitchAndFamily // rm new
  1544. ifi.usWinWeight = m_IFIMETRICS.usWinWeight; // usWinWeight // rm new
  1545. ifi.flInfo = m_IFIMETRICS.flInfo; // flInfo // rm new
  1546. ifi.fsSelection = m_IFIMETRICS.fsSelection; // fsSelection // rm new
  1547. ifi.fsType = FM_NO_EMBEDDING; // fsType // rm new
  1548. ifi.fwdUnitsPerEm = m_IFIMETRICS.fwdUnitsPerEm; // fwdUnitsPerEm // rm new
  1549. ifi.fwdLowestPPEm = m_IFIMETRICS.fwdLowestPPEm; // fwdLowestPPEm // rm new
  1550. ifi.fwdWinAscender = m_IFIMETRICS.fwdWinAscender; // fwdWinAscender // rm new
  1551. ifi.fwdWinDescender = m_IFIMETRICS.fwdWinDescender; // fwdWinDescender // rm new
  1552. ifi.fwdMacAscender = m_IFIMETRICS.fwdWinAscender; // fwdMacAscender // rm replaced
  1553. ifi.fwdMacDescender = m_IFIMETRICS.fwdWinAscender - m_wHeight; // fwdMacDescender // rm replaced
  1554. ifi.fwdMacLineGap = m_IFIMETRICS.fwdMacLineGap; // fwdMacLineGap
  1555. ifi.fwdTypoAscender = m_IFIMETRICS.fwdWinAscender; // fwdTypoAscender // rm replaced
  1556. ifi.fwdTypoDescender = m_IFIMETRICS.fwdWinAscender - m_wHeight; // fwdTypoDescender // rm replaced
  1557. ifi.fwdTypoLineGap = m_IFIMETRICS.fwdMacLineGap; // fwdTypoLineGap
  1558. ifi.fwdAveCharWidth = m_IFIMETRICS.fwdAveCharWidth; // fwdAveCharWidth // rm new
  1559. ifi.fwdMaxCharInc = m_IFIMETRICS.fwdMaxCharInc; // fwdMaxCharInc // rm new
  1560. ifi.fwdCapHeight = m_IFIMETRICS.fwdCapHeight; // fwdCapHeight // rm new
  1561. ifi.fwdXHeight = m_IFIMETRICS.fwdXHeight; // fwdXHeight // rm new
  1562. ifi.fwdSubscriptXSize = m_IFIMETRICS.fwdSubscriptXSize; // fwdSubscriptXSize // rm new
  1563. ifi.fwdSubscriptYSize = m_IFIMETRICS.fwdSubscriptYSize; // fwdSubscriptYSize // rm new
  1564. ifi.fwdSubscriptXOffset = m_IFIMETRICS.fwdSubscriptXOffset; // fwdSubscriptXOffset // rm new
  1565. ifi.fwdSubscriptYOffset = m_IFIMETRICS.fwdSubscriptYOffset; // fwdSuperscriptYOffset // rm new
  1566. ifi.fwdSuperscriptXSize = m_IFIMETRICS.fwdSuperscriptXSize; // fwdSuperscriptXSize // rm new
  1567. ifi.fwdSuperscriptYSize = m_IFIMETRICS.fwdSuperscriptYSize; // fwdSubscriptYOffset // rm new
  1568. ifi.fwdSuperscriptXOffset = m_IFIMETRICS.fwdSuperscriptXOffset; // fwdSuperscriptXOffset // rm new
  1569. ifi.fwdSuperscriptYOffset = m_IFIMETRICS.fwdSuperscriptYOffset; // fwdSuperscriptYOffset // rm new
  1570. ifi.fwdUnderscoreSize = m_IFIMETRICS.fwdUnderscoreSize; // fwdUnderscoreSize // rm new
  1571. ifi.fwdUnderscorePosition = m_IFIMETRICS.fwdUnderscorePosition; // fwdUnderscorePosition // rm new
  1572. ifi.fwdStrikeoutSize = m_IFIMETRICS.fwdStrikeoutSize; // fwdStrikeoutSize // rm new
  1573. ifi.fwdStrikeoutPosition = m_IFIMETRICS.fwdStrikeoutPosition; // fwdStrikeoutPosition // rm new
  1574. //------------------------------------------------------------------------------------------------------------------------------------------
  1575. ifi.chFirstChar = m_IFIMETRICS.chFirstChar; // chFirstChar // rm new
  1576. ifi.chLastChar = m_IFIMETRICS.chLastChar; // chLastChar // rm new
  1577. ifi.chDefaultChar = m_IFIMETRICS.chDefaultChar; // chDefaultChar // rm new
  1578. ifi.chBreakChar = m_IFIMETRICS.chBreakChar; // chBreakChar // rm new
  1579. ifi.wcFirstChar = m_IFIMETRICS.wcFirstChar; // wcFirstChar // rm new
  1580. ifi.wcLastChar = m_IFIMETRICS.wcLastChar; // wcLastChar // rm new
  1581. ifi.wcDefaultChar = m_IFIMETRICS.wcDefaultChar; // wcDefaultChar // rm new
  1582. ifi.wcBreakChar = m_IFIMETRICS.wcBreakChar; // wcBreakChar // rm new
  1583. ifi.ptlBaseline.x = m_IFIMETRICS.ptlBaseline.x; // ptlBaseline.x
  1584. ifi.ptlBaseline.y = m_IFIMETRICS.ptlBaseline.y; // ptlBaseline.y
  1585. ifi.ptlAspect.x = m_IFIMETRICS.ptlAspect.x; // ptlAspect.x // rm new
  1586. ifi.ptlAspect.y = m_IFIMETRICS.ptlAspect.y; // ptlAspect.y // rm new
  1587. //------------------------------------------------------------------------------------------------------------------------------------------
  1588. // ifi.ptlBaseline.x = 1; // ptlBaseline.x
  1589. // ifi.ptlBaseline.y = 0; // ptlBaseline.y
  1590. //
  1591. // ifi.ptlAspect.x = m_UNIDRVINFO.wXRes; // ptlAspect.x // rm new
  1592. // ifi.ptlAspect.y = m_UNIDRVINFO.wYRes; // ptlAspect.y // rm new
  1593. //------------------------------------------------------------------------------------------------------------------------------------------
  1594. ifi.ptlCaret.x = m_IFIMETRICS.ptlCaret.x; // ptlCaret.x // rm new
  1595. ifi.ptlCaret.y = m_IFIMETRICS.ptlCaret.y; // ptlCaret.y // rm new
  1596. // ifi.ptlCaret.x = m_ItalicAngle ? (long) ((double) 10000.0 * // ptlCaret.x // rm ori
  1597. // tan(((double) m_ItalicAngle) / gdConvertRadToDegree)) : 0;
  1598. // ifi.ptlCaret.y = m_ItalicAngle ? 10000 : 1; // ptlCaret.y // rm ori
  1599. //------------------------------------------------------------------------------------------------------------------------------------------
  1600. memcpy(ifi.achVendId, "Unkn", 4); // achVendId // rm ori
  1601. //------------------------------------------------------------------------------------------------------------------------------------------
  1602. ifi.cKerningPairs = m_csoaKern.GetSize(); // cKerningPairs // rm ori
  1603. //------------------------------------------------------------------------------------------------------------------------------------------
  1604. ifi.rclFontBox.left = m_IFIMETRICS.rclFontBox.left; // rclFontBox.left // rm new
  1605. ifi.rclFontBox.top = m_IFIMETRICS.rclFontBox.top; // rclFontBox.top // rm new
  1606. ifi.rclFontBox.right = m_IFIMETRICS.rclFontBox.right; // rclFontBox.right // rm new
  1607. ifi.rclFontBox.bottom = m_IFIMETRICS.rclFontBox.bottom; // rclFontBox.bottom // rm new
  1608. //------------------------------------------------------------------------------------------------------------------------------------------
  1609. ifi.ulPanoseCulture = FM_PANOSE_CULTURE_LATIN; // ulPanoseCulture // rm ori
  1610. //------------------------------------------------------------------------------------------------------------------------------------------
  1611. // panose .bWeight // rm ori
  1612. ifi.panose.bWeight = (m_IFIMETRICS.usWinWeight >= FW_BOLD) ? PAN_WEIGHT_BOLD :
  1613. (m_IFIMETRICS.usWinWeight > FW_EXTRALIGHT) ? PAN_WEIGHT_MEDIUM : PAN_WEIGHT_LIGHT;
  1614. ifi.panose.bFamilyType = m_IFIMETRICS.panose.bFamilyType; // panose // rm new
  1615. ifi.panose.bSerifStyle = m_IFIMETRICS.panose.bSerifStyle;
  1616. ifi.panose.bProportion = m_IFIMETRICS.panose.bProportion;
  1617. ifi.panose.bContrast = m_IFIMETRICS.panose.bContrast;
  1618. ifi.panose.bStrokeVariation = m_IFIMETRICS.panose.bStrokeVariation;
  1619. ifi.panose.bArmStyle = m_IFIMETRICS.panose.bArmStyle;
  1620. ifi.panose.bLetterform = m_IFIMETRICS.panose.bLetterform;
  1621. ifi.panose.bMidline = m_IFIMETRICS.panose.bMidline;
  1622. ifi.panose.bXHeight = m_IFIMETRICS.panose.bXHeight;
  1623. // ifi.panose.bFamilyType = ifi.panose.bSerifStyle = // panose // rm ori
  1624. // ifi.panose.bProportion = ifi.panose.bContrast =
  1625. // ifi.panose.bStrokeVariation = ifi.panose.bArmStyle =
  1626. // ifi.panose.bLetterform = ifi.panose.bMidline =
  1627. // ifi.panose.bXHeight = PAN_ANY;
  1628. //------------------------------------------------------------------------------------------------------------------------------------------
  1629. // Convert and "place" the various name strings
  1630. CUniString cusUnique(m_csUnique), cusStyle(m_csStyle),
  1631. cusFace(m_csFace), cusFamily(m_csaFamily[0]);
  1632. ifi.dpwszFamilyName = ifi.cjThis;
  1633. for (int i = 1; i < m_csaFamily.GetSize(); i++)
  1634. {
  1635. CUniString cusWork(m_csaFamily[i]);
  1636. cusFamily.Append(cusWork);
  1637. }
  1638. if (m_csaFamily.GetSize() > 1)
  1639. {
  1640. cusFamily.Add(0);
  1641. ifi.flInfo |= FM_INFO_FAMILY_EQUIV;
  1642. }
  1643. ifi.cjThis += cusFamily.GetSize();
  1644. ifi.dpwszFaceName = ifi.cjThis;
  1645. ifi.cjThis += cusFace.GetSize();
  1646. ifi.dpwszUniqueName = ifi.cjThis;
  1647. ifi.cjThis += cusUnique.GetSize();
  1648. ifi.dpwszStyleName = ifi.cjThis;
  1649. ifi.cjThis += cusStyle.GetSize();
  1650. //------------------------------------------------------------------------------------------------------------------------------------------
  1651. // The next field must be DWORD aligned, so see what padding
  1652. // is needed.
  1653. unsigned uAdjustIFI = (sizeof ifi.cjThis -
  1654. (ifi.cjThis % sizeof ifi.cjThis)) % sizeof ifi.cjThis;
  1655. ifi.cjThis += uAdjustIFI;
  1656. unsigned uSim = !!m_pcfdBold + !!m_pcfdItalic + !!m_pcfdBoth; // Finally, Allow for the size of any Font Difference structures.
  1657. ifi.dpFontSim = uSim ? ifi.cjThis : 0;
  1658. ufmh.dwSize += ifi.cjThis += uSim * sizeof(FONTDIFF) + !!uSim * sizeof(FONTSIM) + dwAdd_IFI;
  1659. //------------------------------------------------------------------------------------------------------------------------------------------
  1660. // EXTTEXTMETRIC
  1661. ufmh.loExtTextMetric = 0; // Preset ufm exttextmetric offset to 0.
  1662. if(m_fSave_EXT) // If user wants to save the EXTTEXTMETRIC data
  1663. {
  1664. ufmh.loExtTextMetric = ufmh.dwSize; // Set ufm exttextmetric offset. Note, this
  1665. // offset just happens to be the current ufmh.dwSize.
  1666. if(dwAdd_ExtTextM = ufmh.loExtTextMetric & 0x07){
  1667. dwAdd_ExtTextM = OS_BYTE - dwAdd_ExtTextM;
  1668. ufmh.loExtTextMetric += dwAdd_ExtTextM;
  1669. }
  1670. ufmh.dwSize += m_EXTTEXTMETRIC.emSize = sizeof(EXTTEXTMETRIC); // Increase size of ufmh.dwSize to accomodate
  1671. // exttextmetric structure.
  1672. ufmh.dwSize +=dwAdd_ExtTextM;
  1673. }
  1674. //------------------------------------------------------------------------------------------------------------------------------------------
  1675. // CHARACTER WIDTHS DATA
  1676. // Calculate size of width table (if there is one)
  1677. //raid 154639
  1678. ufmh.loWidthTable = IsVariableWidth() * ufmh.dwSize; // set ufm width table offset. Note, this
  1679. if(dwAdd_WidthTable = ufmh.loWidthTable & 0x07){ // offset just happens to be the current ufmh.dwSize.
  1680. dwAdd_WidthTable = OS_BYTE - dwAdd_WidthTable;
  1681. ufmh.loWidthTable += dwAdd_WidthTable;
  1682. }
  1683. if (IsVariableWidth()) // Width table, but only if there is an associated GTT.
  1684. { // For now, we just need to calculate the size of the table
  1685. unsigned uRuns = 0, uGlyphs = 0;
  1686. if (DBCSFont()) // DBCS
  1687. {
  1688. unsigned u = (unsigned) m_cpaGlyphs.GetSize(); // Determine the number of runs needed
  1689. do
  1690. {
  1691. while (u-- && !m_cwaWidth[u]); // DBCS has 0 width
  1692. if (u == (unsigned) -1) break; // We're done!
  1693. uRuns++, uGlyphs++;
  1694. while (u-- && m_cwaWidth[u])
  1695. uGlyphs++;
  1696. }
  1697. while (u != (unsigned) -1);
  1698. }
  1699. else
  1700. {
  1701. uRuns++;
  1702. uGlyphs = (unsigned)m_cwaWidth.GetSize();
  1703. }
  1704. ufmh.dwSize += sizeof (WIDTHTABLE) + --uRuns * sizeof (WIDTHRUN) +
  1705. uGlyphs * sizeof (WORD) + dwAdd_WidthTable;
  1706. }
  1707. //------------------------------------------------------------------------------------------------------------------------------------------
  1708. // KERNING PAIRS DATA
  1709. // Calculate size of Kerning table (if there is one)
  1710. ufmh.loKernPair = CanKern() ? ufmh.dwSize : 0; // set ufm Kerning table offset. Note, this
  1711. // offset just happens to be the current ufmh.dwSize.
  1712. // A "secret" kern pair of all 0's must end this,
  1713. // so this size is in fact correct. Also note that
  1714. // padding screws up the size of the KERNDATA structure.
  1715. if (CanKern()){
  1716. if(dwAdd_KerPair = ufmh.loKernPair & 0x07) { // offset just happens to be the current ufmh.dwSize.
  1717. dwAdd_KerPair = OS_BYTE - dwAdd_KerPair;
  1718. ufmh.loKernPair += dwAdd_KerPair;
  1719. }
  1720. ufmh.dwSize +=
  1721. ((sizeof (KERNDATA) - sizeof (FD_KERNINGPAIR)) & 0xFFFC) +
  1722. ((1 + m_csoaKern.GetSize()) * sizeof (FD_KERNINGPAIR)) + dwAdd_KerPair;
  1723. }
  1724. //------------------------------------------------------------------------------------------------------------------------------------------
  1725. // All sizes have been calculated, and the important structures have
  1726. // been initialized. Time to start writing all this great stuff!
  1727. //------------------------------------------------------------------------------------------------------------------------------------------
  1728. cfUFM.Write(&ufmh, sizeof ufmh); // write UNIFM_HDR Header
  1729. //------------------------------------------------------------------------------------------------------------------------------------------
  1730. if (dwAdd_UniDrv)
  1731. cfUFM.Write(InsertZero, dwAdd_UniDrv);
  1732. cfUFM.Write(&m_UNIDRVINFO, sizeof m_UNIDRVINFO); // write UNIDRVINFO // rm new
  1733. /* if (dwAdd_SelectedFont)
  1734. cfUFM.Write (InsertZero,dwAdd_SelectedFont); */
  1735. m_ciSelect.WriteEncoding(cfUFM);
  1736. /* if (dwAdd_UnSelectedFont)
  1737. cfUFM.Write (InsertZero,dwAdd_UnSelectedFont); */
  1738. m_ciDeselect.WriteEncoding(cfUFM);
  1739. cfUFM.Write(ufmh.dwReserved, uAdjustUDI); // write Padding
  1740. //------------------------------------------------------------------------------------------------------------------------------------------
  1741. if (dwAdd_IFI)
  1742. cfUFM.Write(InsertZero, dwAdd_IFI);
  1743. cfUFM.Write(&ifi, sizeof ifi); // write IFIMETRICS
  1744. cfUFM.Write(&ifie, sizeof ifie); // write IFIEXTRA
  1745. cusFamily.Write(cfUFM); // write "Family"
  1746. cusFace.Write(cfUFM); // write "Face"
  1747. cusUnique.Write(cfUFM); // write "Unique name"
  1748. cusStyle.Write(cfUFM); // write "Style"
  1749. cfUFM.Write(ufmh.dwReserved, uAdjustIFI); // write Padding
  1750. //------------------------------------------------------------------------------------------------------------------------------------------
  1751. if (m_pcfdBold || m_pcfdItalic || m_pcfdBoth) // Any Font difference structures
  1752. {
  1753. FONTSIM fs;
  1754. unsigned uWhere = sizeof fs;
  1755. fs.dpBold = m_pcfdBold ? uWhere : 0;
  1756. uWhere += !!m_pcfdBold * sizeof (FONTDIFF);
  1757. fs.dpItalic = m_pcfdItalic ? uWhere : 0;
  1758. uWhere += !!m_pcfdItalic * sizeof (FONTDIFF);
  1759. //TRACE("Italic metrics = %d, %d %d %d\n", m_pcfdItalic->Metric(0), m_pcfdItalic->Metric(1), m_pcfdItalic->Metric(2), m_pcfdItalic->Metric(3)) ;
  1760. fs.dpBoldItalic = m_pcfdBoth ? uWhere : 0;
  1761. cfUFM.Write(&fs, sizeof fs);
  1762. if (m_pcfdBold) m_pcfdBold->Store(cfUFM, m_IFIMETRICS.fsSelection | FM_SEL_BOLD); // rm new
  1763. if (m_pcfdItalic) m_pcfdItalic->Store(cfUFM, m_IFIMETRICS.fsSelection | FM_SEL_ITALIC);
  1764. if (m_pcfdBoth) m_pcfdBoth->Store(cfUFM, m_IFIMETRICS.fsSelection | FM_SEL_BOLD| FM_SEL_ITALIC);
  1765. // if (m_pcfdBold) m_pcfdBold->Store(cfUFM, m_wfStyle | FM_SEL_BOLD); // rm ori
  1766. // if (m_pcfdItalic) m_pcfdItalic->Store(cfUFM, m_wfStyle | FM_SEL_ITALIC);
  1767. // if (m_pcfdBoth) m_pcfdBoth->Store(cfUFM, m_wfStyle | FM_SEL_BOLD| FM_SEL_ITALIC);
  1768. }
  1769. //------------------------------------------------------------------------------------------------------------------------------------------
  1770. if (m_fSave_EXT) // write EXTTEXTMETRIC
  1771. if (dwAdd_ExtTextM)
  1772. cfUFM.Write(InsertZero, dwAdd_ExtTextM);
  1773. cfUFM.Write(&m_EXTTEXTMETRIC, sizeof(EXTTEXTMETRIC) );
  1774. //------------------------------------------------------------------------------------------------------------------------------------------
  1775. // Width table
  1776. if (IsVariableWidth())
  1777. if (!DBCSFont()) // Not DBCS - easy! (Handles always start at 1
  1778. {
  1779. WIDTHTABLE wdt = { sizeof wdt, 1,
  1780. {1, (WORD)m_cpaGlyphs.GetSize(), sizeof wdt}};
  1781. if(dwAdd_WidthTable) // 154639
  1782. cfUFM.Write(InsertZero, dwAdd_WidthTable);
  1783. cfUFM.Write(&wdt, sizeof wdt);
  1784. cfUFM.Write(m_cwaWidth.GetData(),
  1785. (unsigned)(m_cwaWidth.GetSize() * sizeof (WORD)));
  1786. }
  1787. else // DBCS - This case is a bit nastier
  1788. {
  1789. CByteArray cbaTable;
  1790. CWordArray cwaSize;
  1791. cbaTable.SetSize(sizeof(WIDTHTABLE) - sizeof(WIDTHRUN));
  1792. PWIDTHTABLE pwdt = (PWIDTHTABLE) cbaTable.GetData();
  1793. pwdt -> dwRunNum = 0;
  1794. // Calculate and fill in the WIDTHRUN structures and the
  1795. // Size array
  1796. unsigned u = 0, uMax = (unsigned) m_cpaGlyphs.GetSize();
  1797. do
  1798. {
  1799. while (u < uMax && !m_cwaWidth[u++]);
  1800. if (u == uMax) break; // We're done!
  1801. // We've found a run- lots of work to do
  1802. cbaTable.InsertAt(cbaTable.GetSize(), 0, // Add a run to the table
  1803. sizeof (WIDTHRUN));
  1804. pwdt = (PWIDTHTABLE) cbaTable.GetData(); // Remember the glyph handle is 1-based.
  1805. pwdt->WidthRun[pwdt->dwRunNum].wStartGlyph = --u + 1;
  1806. pwdt->WidthRun[pwdt->dwRunNum].wGlyphCount = 0;
  1807. pwdt->WidthRun[pwdt->dwRunNum].loCharWidthOffset =
  1808. (DWORD)(cwaSize.GetSize() * sizeof (WORD));
  1809. do
  1810. {
  1811. cwaSize.Add(m_cwaWidth[u]);
  1812. pwdt -> WidthRun[pwdt->dwRunNum].wGlyphCount++;
  1813. }
  1814. while (++u < uMax && m_cwaWidth[u]);
  1815. pwdt->dwRunNum++; // End of the run!
  1816. }
  1817. while (u < uMax);
  1818. // OK, now we have to add the total size of the WIDTHTABLE
  1819. // to the various offsets, but we are otherwise ready to rock
  1820. // and roll.
  1821. pwdt->dwSize = (DWORD)cbaTable.GetSize();
  1822. for (u = 0; u < pwdt->dwRunNum; u++)
  1823. pwdt->WidthRun[u].loCharWidthOffset += pwdt->dwSize;
  1824. if(dwAdd_WidthTable) // 154639
  1825. cfUFM.Write(InsertZero, dwAdd_WidthTable);
  1826. cfUFM.Write(pwdt, pwdt -> dwSize); // write width table
  1827. for (u = 0; u < pwdt -> dwRunNum; u++)
  1828. cfUFM.Write(cwaSize.GetData() +
  1829. pwdt -> WidthRun[u].wStartGlyph - 1,
  1830. pwdt -> WidthRun[u].wGlyphCount * sizeof (WORD));
  1831. }
  1832. //------------------------------------------------------------------------------------------------------------------------------------------
  1833. if (CanKern()) // Kern Pairs
  1834. {
  1835. // KERNDATA is DWORD-packed, but FD_KERNINGPAIR is WORD-packed
  1836. // the following trick code allows for any slop.
  1837. KERNDATA kd = {0xFFFC & (sizeof kd - sizeof kd.KernPair),
  1838. m_csoaKern.GetSize()};
  1839. kd.dwSize += (1 + kd.dwKernPairNum) * sizeof kd.KernPair;
  1840. if(dwAdd_KerPair) // 154639
  1841. cfUFM.Write(InsertZero, dwAdd_KerPair);
  1842. cfUFM.Write(&kd, 0xFFFC & (sizeof kd - sizeof kd.KernPair));
  1843. for (unsigned u = 0; u < m_csoaKern.GetSize(); u++) {
  1844. CKern *pck = (CKern *) m_csoaKern[u] ;
  1845. WCHAR wcf = pck->First() ;
  1846. WCHAR wcs = pck->Second() ;
  1847. short sa = pck->Amount() ;
  1848. ((CKern *) m_csoaKern[u]) -> Store(cfUFM);
  1849. } ;
  1850. // Now for the "secret" sentinel-
  1851. CKern ck; // Just happens to 0-init!
  1852. ck.Store(cfUFM);
  1853. }
  1854. }
  1855. //------------------------------------------------------------------------------------------------------------------------------------------
  1856. catch (CException *pce)
  1857. {
  1858. pce -> ReportError();
  1859. pce -> Delete();
  1860. return FALSE;
  1861. }
  1862. if(!bStoreFormWokspace) //raid 244123
  1863. Changed(FALSE);
  1864. return TRUE; // Return triumphant to whoever deigned to need this service.
  1865. }
  1866. /*****************************************************************************
  1867. CFontInfo::StoreGTTCPOnly
  1868. When a UFM is loaded during a workspace load and the UFM does not have a
  1869. valid GTT or CP, the UFM cannot be saved normally because there are several
  1870. parts of the UFM that were not loaded correctly or at all because of the
  1871. missing data.
  1872. When this situation is detected, this routine is called so the - supposedly -
  1873. good info in the disk file is not overwritten by bad data. In addition,
  1874. Store() will blow when it tries to use nonexistent UFM data.
  1875. This routine will just save the what we hope is corrected GTT and/or CP data.
  1876. This is done without changing any of the other data in the file. Next, the
  1877. UFM is reloaded. If all goes well, the UFM is correctly loaded so that
  1878. normal editting and saving can be performed from this point on.
  1879. TRUE is returned if the GTT and CP are successfully saved. Otherwise, FALSE
  1880. is returned.
  1881. ******************************************************************************/
  1882. BOOL CFontInfo::StoreGTTCPOnly(LPCTSTR lpstrFile)
  1883. {
  1884. // Remind the user about what is going to happen.
  1885. AfxMessageBox(IDS_GTTCPOnlySaved, MB_ICONINFORMATION) ;
  1886. // Perform the steps required to update the GTT/CP in the UFM file.
  1887. try {
  1888. // Begin by opening the file in a way that will not truncate existing
  1889. // files.
  1890. UINT nopenflags = CFile::modeNoTruncate | CFile::modeCreate ;
  1891. nopenflags |= CFile::modeWrite | CFile::shareExclusive ;
  1892. CFile cfufm(lpstrFile, nopenflags) ;
  1893. // Seek to the file positon that we want change.
  1894. UNIFM_HDR ufmh ;
  1895. DWORD dwseekpos ;
  1896. dwseekpos = (DWORD)PtrToUlong(&ufmh.ulDefaultCodepage) - (DWORD)PtrToUlong(&ufmh) ;
  1897. cfufm.Seek(dwseekpos, CFile::begin) ;
  1898. // Load the fields in the UFM header that we want to save and write
  1899. // them out.
  1900. ufmh.ulDefaultCodepage = m_ulDefaultCodepage ;
  1901. ufmh.lGlyphSetDataRCID = m_lGlyphSetDataRCID ;
  1902. UINT nwritebytes = sizeof(ufmh.ulDefaultCodepage)
  1903. + sizeof(ufmh.lGlyphSetDataRCID) ;
  1904. cfufm.Write((void*) &ufmh.ulDefaultCodepage, nwritebytes) ;
  1905. // Move the file pointer to the end of the file and close it.
  1906. cfufm.SeekToEnd() ;
  1907. cfufm.Close() ;
  1908. }
  1909. catch (CException *pce) {
  1910. pce->ReportError() ;
  1911. pce->Delete() ;
  1912. return FALSE ;
  1913. } ;
  1914. Changed(FALSE) ;
  1915. // If the UFM was loaded from a workspace, try to use the workspace data to
  1916. // find and load a pointer to the new GTT and finish loading the font.
  1917. m_pcgmTranslation = NULL ;
  1918. if (m_bLoadedByWorkspace) {
  1919. CDriverResources* pcdr = (CDriverResources*) GetWorkspace() ;
  1920. if (pcdr)
  1921. pcdr->LinkAndLoadFont(*this, false) ;
  1922. else
  1923. Load(false) ;
  1924. // If the UFM was loaded stand alone the first time, reload it the same way
  1925. // and let the load routine handle finding the GTT info.
  1926. } else
  1927. Load(false) ;
  1928. // If reloading the UFM successfully associated a GTT or CP with the UFM,
  1929. // clear the m_bWSLoadButNoGTTCP flag. Then tell the user that the UFM
  1930. // can be editted normally now.
  1931. if (m_pcgmTranslation) {
  1932. SetNoGTTCP(false) ;
  1933. CString csmsg ;
  1934. csmsg.Format(IDS_UFMOKNow, Name()) ;
  1935. AfxMessageBox(csmsg, MB_ICONINFORMATION) ;
  1936. } ;
  1937. // All went well so...
  1938. return TRUE ;
  1939. }
  1940. /*****************************************************************************
  1941. CFontInfo::CreateEditor
  1942. This member function launches an editing view for the font.
  1943. ******************************************************************************/
  1944. CMDIChildWnd* CFontInfo::CreateEditor()
  1945. {
  1946. CFontInfoContainer* pcficMe= new CFontInfoContainer(this, FileName());
  1947. pcficMe -> SetTitle(m_pcbnWorkspace -> Name() + _TEXT(": ") + Name()); // Make up a cool title
  1948. CMDIChildWnd *pcmcwNew;
  1949. pcmcwNew = (CMDIChildWnd *) m_pcmdt->CreateNewFrame(pcficMe, NULL);
  1950. if (pcmcwNew)
  1951. {
  1952. m_pcmdt -> InitialUpdateFrame(pcmcwNew, pcficMe, TRUE);
  1953. m_pcmdt -> AddDocument(pcficMe);
  1954. }
  1955. return pcmcwNew;
  1956. }
  1957. /******************************************************************************
  1958. CFontInfo::Serialize
  1959. This is responsible for storing and restoring the entire maze of data in
  1960. persistent object storage.
  1961. ******************************************************************************/
  1962. void CFontInfo::Serialize(CArchive& car) {
  1963. // We only serialize what's needed to use the UFM file in the editor,
  1964. // i.e., the glue needed to hold us in the driver workspace.
  1965. CProjectNode::Serialize(car);
  1966. }
  1967. /*****************************************************************************
  1968. CFontInfo::GetFontSimDataPtr
  1969. Return a pointer to the requested font simulation data.
  1970. ******************************************************************************/
  1971. CWordArray* CFontInfo::GetFontSimDataPtr(int nid)
  1972. {
  1973. switch (nid) {
  1974. case ItalicDiff:
  1975. if (m_pcfdItalic == NULL)
  1976. ASSERT(0) ;
  1977. return m_pcfdItalic->GetFontSimDataPtr() ;
  1978. case BoldDiff:
  1979. if (m_pcfdBold == NULL)
  1980. ASSERT(0) ;
  1981. return m_pcfdBold->GetFontSimDataPtr() ;
  1982. case BothDiff:
  1983. if (m_pcfdBoth == NULL)
  1984. ASSERT(0) ;
  1985. return m_pcfdBoth->GetFontSimDataPtr() ;
  1986. default:
  1987. ASSERT(0) ;
  1988. } ;
  1989. // This point should never be reached.
  1990. return NULL ;
  1991. }
  1992. /******************************************************************************
  1993. CFontInfo::EnableSim
  1994. This method is called to turn simulation on or off for the specified item.
  1995. It receives a reference to the editor's pointer for the same item.
  1996. ******************************************************************************/
  1997. void CFontInfo::EnableSim(unsigned uSim, BOOL bOn, CFontDifference*& pcfd)
  1998. {
  1999. CFontDifference*& pcfdTarget = uSim ? (uSim == BothDiff) ? m_pcfdBoth : m_pcfdBold : m_pcfdItalic;
  2000. if (bOn == !!pcfd && pcfdTarget == pcfd) return; // Clear out any irrelevant calls
  2001. if (bOn && pcfdTarget) // If this call is just to init pcfd, do it and leave
  2002. {
  2003. pcfd = pcfdTarget;
  2004. return;
  2005. }
  2006. if (bOn)
  2007. // pcfd = pcfdTarget = pcfd ? pcfd : new CFontDifference(m_wWeight, m_wMaximumIncrement, m_wAverageWidth, // rm ori
  2008. // uSim == BoldDiff ? m _cwaSpecial[ItalicAngle] : 175, this);
  2009. pcfd = pcfdTarget = pcfd ? pcfd : new CFontDifference(m_IFIMETRICS.usWinWeight, m_IFIMETRICS.fwdMaxCharInc, m_IFIMETRICS.fwdAveCharWidth,
  2010. uSim == BoldDiff ? m_ItalicAngle : 175, this);
  2011. else
  2012. pcfdTarget = NULL; // pcfd will already have been set correctly
  2013. Changed();
  2014. }
  2015. /******************************************************************************
  2016. CFontInfo::FillKern
  2017. This preps the passed CListCtrl, if necessary, and fills it with the kerning
  2018. information.
  2019. ******************************************************************************/
  2020. void CFontInfo::FillKern(CListCtrl& clcView)
  2021. {
  2022. for (unsigned u = 0; u < m_csoaKern.GetSize(); u++)
  2023. {
  2024. CString csWork;
  2025. CKern& ckThis = *(CKern *) m_csoaKern[u];
  2026. csWork.Format("%d", ckThis.Amount());
  2027. int idItem = clcView.InsertItem(u, csWork);
  2028. clcView.SetItemData(idItem, u);
  2029. csWork.Format("0x%X", ckThis.First());
  2030. clcView.SetItem(idItem, 1, LVIF_TEXT, csWork, -1, 0, 0, u);
  2031. csWork.Format("0x%X", ckThis.Second());
  2032. clcView.SetItem(idItem, 2, LVIF_TEXT, csWork, -1, 0, 0, u);
  2033. }
  2034. }
  2035. /******************************************************************************
  2036. CFontInfo::LoadBadKerningInfo
  2037. Check the kerning pairs to see if they reference code points that are not in
  2038. the UFM's GTT. If any are found, load them into the specified list control.
  2039. Return true if any bad kerning pairs were found. Otherwise, return false.
  2040. ******************************************************************************/
  2041. bool CFontInfo::LoadBadKerningInfo(CListCtrl& clcbaddata)
  2042. {
  2043. // Declare the variables needed to check for bad kerning data
  2044. unsigned unumkerns = m_csoaKern.GetSize() ;
  2045. CString cs ;
  2046. bool bfoundbad = false ;
  2047. // Loop through each kerning class and check it.
  2048. for (unsigned u = 0 ; u < unumkerns ; u++) {
  2049. CKern& ckThis = *(CKern *) m_csoaKern[u] ;
  2050. // If each code point in this kerning pair is still a valid code point
  2051. // for the GTT, skip this kerning pair.
  2052. if (CodePointInGTT(ckThis.First()) && CodePointInGTT(ckThis.Second()))
  2053. continue ;
  2054. // Add this kerning pair's data to the list of bad data.
  2055. cs.Format("%d", ckThis.Amount()) ;
  2056. int idItem = clcbaddata.InsertItem(u, cs) ;
  2057. clcbaddata.SetItemData(idItem, u) ;
  2058. cs.Format("0x%X", ckThis.First()) ;
  2059. clcbaddata.SetItem(idItem, 1, LVIF_TEXT, cs, -1, 0, 0, u) ;
  2060. cs.Format("0x%X", ckThis.Second()) ;
  2061. clcbaddata.SetItem(idItem, 2, LVIF_TEXT, cs, -1, 0, 0, u) ;
  2062. bfoundbad = true ;
  2063. } ;
  2064. return bfoundbad ;
  2065. }
  2066. /******************************************************************************
  2067. CFontInfo::CodePointInGTT
  2068. Return true if the specified code point is in the GTT. Otherwise, return
  2069. false.
  2070. ******************************************************************************/
  2071. bool CFontInfo::CodePointInGTT(WORD wcodepoint)
  2072. {
  2073. int nelts = (int)m_cpaGlyphs.GetSize() ;// Number of elements in glyphs array
  2074. int nleft, nright, ncheck ; // Variables needed to search array
  2075. WORD wgttcp ;
  2076. // Try to find the codepoint in the GTT
  2077. for (nleft = 0, nright = nelts - 1 ; nleft <= nright ; ) {
  2078. ncheck = (nleft + nright) >> 1 ;
  2079. wgttcp = ((CGlyphHandle *) m_cpaGlyphs[ncheck])->CodePoint() ;
  2080. //TRACE("Key[%d] = '0x%x', CP = '0x%x'\n", ncheck, wgttcp, wcodepoint) ;
  2081. if (wgttcp > wcodepoint)
  2082. nright = ncheck - 1 ;
  2083. else if (wgttcp < wcodepoint)
  2084. nleft = ncheck + 1 ;
  2085. else
  2086. return true ; //*** Return true here if match found.
  2087. } ;
  2088. // Return false here because no match found.
  2089. return false ;
  2090. }
  2091. /******************************************************************************
  2092. CFontInfo::AddKern
  2093. This method adds an additional kerning pair into the array. and also inserts
  2094. it into the list view.
  2095. ******************************************************************************/
  2096. void CFontInfo::AddKern(WORD wFirst, WORD wSecond, short sAmount,
  2097. CListCtrl& clcView) {
  2098. for (unsigned u = 0; u < KernCount(); u ++) {
  2099. CKern& ckThis = *(CKern *) m_csoaKern[u];
  2100. if (ckThis.Second() < wSecond)
  2101. continue;
  2102. if (ckThis.Second() > wSecond)
  2103. break;
  2104. _ASSERT(ckThis.First() != wFirst);
  2105. if (ckThis.First() < wFirst)
  2106. continue;
  2107. break;
  2108. }
  2109. FD_KERNINGPAIR fdkp = { wFirst, wSecond, sAmount };
  2110. m_csoaKern.InsertAt(u, new CKern(fdkp));
  2111. CString csWork;
  2112. csWork.Format("%d", sAmount);
  2113. int idItem = clcView.InsertItem(u, csWork);
  2114. clcView.SetItemData(idItem, u);
  2115. csWork.Format("0x%X", wFirst);
  2116. clcView.SetItem(idItem, 1, LVIF_TEXT, csWork, -1, 0, 0, u);
  2117. csWork.Format("0x%X", wSecond);
  2118. clcView.SetItem(idItem, 2, LVIF_TEXT, csWork, -1, 0, 0, u);
  2119. Changed();
  2120. }
  2121. /******************************************************************************
  2122. CFontInfo::SetKernAmount
  2123. This will change the kern amount entry for the specified item.
  2124. ******************************************************************************/
  2125. void CFontInfo::SetKernAmount(unsigned u, short sAmount) {
  2126. if (u >= KernCount()) return;
  2127. CKern &ckThis = *(CKern *) m_csoaKern[u];
  2128. if (sAmount == ckThis.Amount()) return;
  2129. ckThis.SetAmount(sAmount);
  2130. Changed();
  2131. }
  2132. /******************************************************************************
  2133. CFontInfo::MakeKernCopy
  2134. Make a copy of the kerning pairs table.
  2135. ******************************************************************************/
  2136. void CFontInfo::MakeKernCopy()
  2137. {
  2138. // Find out how many entries are in the kerning pairs table.
  2139. int numkerns = m_csoaKern.GetSize() ;
  2140. // Get rid of any entries already in the kerning copy table and set it to
  2141. // the correct size.
  2142. m_csoaKernCopy.RemoveAll() ;
  2143. m_csoaKernCopy.SetSize(numkerns) ;
  2144. // Copy the kerning pairs table entries one at a time so that a new CKern
  2145. // class instance can be allocated, initialized, and saved.
  2146. CKern* pck ;
  2147. for (int n = 0 ; n < numkerns ; n++) {
  2148. pck = new CKern(((CKern*) m_csoaKern[n])->First(),
  2149. ((CKern*) m_csoaKern[n])->Second(),
  2150. ((CKern*) m_csoaKern[n])->Amount()) ;
  2151. m_csoaKernCopy.SetAt(n, pck) ;
  2152. } ;
  2153. }
  2154. /******************************************************************************
  2155. CFontInfo::FillWidths
  2156. This preps the passed CListCtrl, if necessary, and fills it with the
  2157. character width information.
  2158. ******************************************************************************/
  2159. void CFontInfo::FillWidths(CListCtrl& clcView)
  2160. {
  2161. CWaitCursor cwc;
  2162. clcView.SetItemCount((int)m_cpaGlyphs.GetSize());
  2163. for (int u = 0; u < m_cpaGlyphs.GetSize(); u++) {
  2164. if (DBCSFont() && !m_cwaWidth[u])
  2165. continue; // Don't display these code points.
  2166. CString csWork;
  2167. CGlyphHandle& cghThis = *(CGlyphHandle *) m_cpaGlyphs[u];
  2168. csWork.Format("%d", m_cwaWidth[u]);
  2169. int idItem = clcView.InsertItem(u, csWork);
  2170. clcView.SetItemData(idItem, u);
  2171. csWork.Format("0x%04X", cghThis.CodePoint());
  2172. clcView.SetItem(idItem, 1, LVIF_TEXT, csWork, -1, 0, 0, u);
  2173. }
  2174. }
  2175. /******************************************************************************
  2176. CFontInfo::WidthsTableIsOK
  2177. Perform the only consistency check on the widths table that I can think of:
  2178. Make sure that there aren't more widths in the UFM than there are Glyphs in
  2179. the GTT. Return true if the table appears to be ok. Otherwise, return false.
  2180. ******************************************************************************/
  2181. bool CFontInfo::WidthsTableIsOK()
  2182. {
  2183. return (m_cwaWidth.GetSize() <= m_cpaGlyphs.GetSize()) ;
  2184. }
  2185. /******************************************************************************
  2186. CFontInfo::SetWidth
  2187. This member sets the width of a glyph. It also updates the Maximum and
  2188. Average width information if the font is not a DBCS font and the user
  2189. requests it.
  2190. ******************************************************************************/
  2191. void CFontInfo::SetWidth(unsigned uGlyph, WORD wWidth, bool bcalc /*=true*/)
  2192. {
  2193. m_cwaWidth[uGlyph] = wWidth;
  2194. if (bcalc && !DBCSFont())
  2195. CalculateWidths();
  2196. }
  2197. /******************************************************************************
  2198. CFontInfo::CompareGlyphsEx(WORD wOld, WORD wNew, CLinkedList* pcll)
  2199. to Do ; check the old glyph table and new, then change the old linked list
  2200. according to the new glyph table.
  2201. parameter : wOld, wNew ; code point index of new, old glyph table
  2202. CLinkedList* pcll ; linked node containing the codepoint data
  2203. return : new linked list of new gtt.
  2204. ******************************************************************************/
  2205. CLinkedList* CFontInfo::CompareGlyphsEx(WORD wOld, WORD wNew, CLinkedList* pcll)
  2206. { // pcll
  2207. static UINT_PTR dwLinked ;
  2208. static CLinkedList* pcllpre = NULL ;
  2209. static CLinkedList* pclltmp = NULL ;
  2210. static int ncOldGlyphs ;
  2211. static int ncNewGlyphs ;
  2212. if (wOld == 0 && wNew == 0 ) {
  2213. dwLinked = (UINT_PTR)pcll ;
  2214. ncNewGlyphs = (int)m_cwaNewGlyphs.GetSize() ;
  2215. ncOldGlyphs = (int)m_cwaOldGlyphs.GetSize() ;
  2216. }
  2217. if (wNew >= ncNewGlyphs && wOld >= ncOldGlyphs ) {
  2218. pcllpre = NULL ;
  2219. return (CLinkedList*) dwLinked;
  2220. }
  2221. // delete at the end of the glyphs tree
  2222. if (wOld < ncOldGlyphs && wNew >= ncNewGlyphs ) {
  2223. pcllpre = pcll->Next ;
  2224. delete pcll ;
  2225. return CompareGlyphsEx(++wOld,wNew,pcllpre) ;
  2226. }
  2227. // add at the end of the glyphs tree
  2228. // BUG_BUG :: this is called at the second end of the code points.
  2229. // added coded is located between seconde end and first end. // almost fixed.
  2230. if (wNew < ncNewGlyphs && wOld >= ncOldGlyphs - 1 && m_cwaOldGlyphs[wOld] <= m_cwaNewGlyphs[wNew] ) {
  2231. CLinkedList* pcllnew = new CLinkedList ;
  2232. if (!pcllnew) {
  2233. CString csError ;
  2234. csError.LoadString(IDS_ResourceError) ;
  2235. AfxMessageBox(csError,MB_ICONEXCLAMATION) ;
  2236. return (CLinkedList*) dwLinked;
  2237. }
  2238. pcllnew->data = 0 ;
  2239. pcll->Next = pcllnew ;
  2240. return CompareGlyphsEx(wOld,++wNew,pcll->Next) ;
  2241. }
  2242. // Delete
  2243. if (m_cwaOldGlyphs[wOld] < m_cwaNewGlyphs[wNew] ) {
  2244. if (!pcllpre || (pcllpre == pcll) ) {
  2245. pcllpre = pcll->Next ;
  2246. dwLinked = (UINT_PTR)pcllpre ;
  2247. delete pcll ;
  2248. return CompareGlyphsEx(++wOld, wNew,pcllpre) ;
  2249. }
  2250. else{
  2251. if (pclltmp && pclltmp->Next == pcllpre->Next )
  2252. pcllpre = pclltmp ;
  2253. pcllpre->Next = pcll->Next ;
  2254. delete pcll ;
  2255. return CompareGlyphsEx(++wOld, wNew,pcllpre->Next ) ;
  2256. }
  2257. }// Add
  2258. else if (m_cwaOldGlyphs[wOld] > m_cwaNewGlyphs[wNew] ) {
  2259. CLinkedList * pcllnew = new CLinkedList ;
  2260. pcllnew->data = 0 ;
  2261. if (!pcllpre) {
  2262. dwLinked = (UINT_PTR) pcllnew ;
  2263. pcllpre = pcllnew ;
  2264. pcllnew ->Next = pcll ;
  2265. }
  2266. else { // problem when pcllnew->next == pcll
  2267. if (pclltmp && pclltmp == pcllpre->Next )
  2268. pcllpre = pclltmp ;
  2269. pcllnew ->Next = pcllpre->Next ;
  2270. pcllpre->Next = pcllnew ;
  2271. pclltmp = pcllnew ;
  2272. }
  2273. return CompareGlyphsEx(wOld, ++wNew,pcllnew ->Next) ;
  2274. } // no change
  2275. else {
  2276. pcllpre = pcll ;
  2277. return CompareGlyphsEx(++wOld,++wNew,pcll->Next ) ;
  2278. }
  2279. }
  2280. /******************************************************************************
  2281. CFontInfo::CheckReloadWidths
  2282. It is possible that the code points in the UFM's GTT have changed. If that
  2283. is the case, reload the widths info so that they can use the new code point
  2284. info.
  2285. Return true if the widths were reloaded. Otherwise, return false.
  2286. NOTE: This function uses several pieces of CFontInfo::Load(). If changes
  2287. are made to those pieces of code, similar changes may need be made in Load()
  2288. too.
  2289. sunggch : Modify the code in order to synchronize the Widthtable with
  2290. GTT change (add or delete code point)
  2291. Get m_cwaWidth from the CompareGlyphsEx instead of UFM load table
  2292. ******************************************************************************/
  2293. DWORD CLinkedList::m_dwSize ;
  2294. #define MAX_CODE_COUNT 1000
  2295. bool CFontInfo::CheckReloadWidths()
  2296. {
  2297. // Do nothing if this class was loaded standalone or it has no GTT pointer.
  2298. if (!m_bLoadedByWorkspace || m_pcgmTranslation == NULL)
  2299. return false ;
  2300. // Do nothing if the GTT has not changes since the last time the UFM's
  2301. // widths were reloaded.
  2302. if (m_pcgmTranslation->m_ctSaveTimeStamp <= m_ctReloadWidthsTimeStamp && !IsRCIDChanged())
  2303. return false ;
  2304. // Open the UFM file
  2305. CFile cfUFM ;
  2306. if (!cfUFM.Open(m_cfn.FullName(), CFile::modeRead | CFile::shareDenyWrite))
  2307. return false ;
  2308. // Try to load the file- proclaim defeat on any exception.
  2309. CByteArray cbaUFM ; // Loaded with file's contents
  2310. try {
  2311. cbaUFM.SetSize(cfUFM.GetLength()) ;
  2312. cfUFM.Read(cbaUFM.GetData(), (unsigned)cbaUFM.GetSize()) ;
  2313. }
  2314. catch (CException *pce) {
  2315. pce->ReportError() ;
  2316. pce->Delete() ;
  2317. return false ;
  2318. } ;
  2319. PUNIFM_HDR pufmh = (PUNIFM_HDR) cbaUFM.GetData() ; // UNIFM_HDR
  2320. // Do nothing if there is no width table except update the timestamp so that
  2321. // this code isn't executed again.
  2322. if (pufmh->loWidthTable == NULL) {
  2323. m_ctReloadWidthsTimeStamp = CTime::GetCurrentTime() ;
  2324. return false ;
  2325. } ;
  2326. union {
  2327. PBYTE pbwt ;
  2328. PWIDTHTABLE pwt ;
  2329. } ;
  2330. pbwt = cbaUFM.GetData() + pufmh->loWidthTable ;
  2331. // Synchronization of UFM width and Gtt is only supported in the SBCS.
  2332. // BUG_BUG : the interupt happend in the DBCS gtt.
  2333. int oldGlyphs = PtrToInt((PVOID)m_cpaGlyphs.GetSize());
  2334. m_pcgmTranslation->Collect(m_cpaGlyphs) ;
  2335. m_cwaNewGlyphs.SetSize(m_cpaGlyphs.GetSize()) ;
  2336. if (!DBCSFont() && m_cpaGlyphs.GetSize() < MAX_CODE_COUNT && oldGlyphs < MAX_CODE_COUNT && m_cwaOldGlyphs.GetSize()) {
  2337. for (int i = 0 ; i < m_cpaGlyphs.GetSize() ; i ++ ) {
  2338. CGlyphHandle& cghThis = *(CGlyphHandle *) m_cpaGlyphs[i];
  2339. m_cwaNewGlyphs.SetAt(i,cghThis.CodePoint() ) ;
  2340. }
  2341. CLinkedList* pcll = new CLinkedList ;
  2342. CLinkedList* pcll_pre = NULL ;
  2343. UINT_PTR dwLinked = (UINT_PTR) pcll ;
  2344. // convert WordArray into LinkedList
  2345. for( i = 0 ; i < m_cwaWidth.GetSize() ; i ++ ) {
  2346. pcll->data = m_cwaWidth[i];
  2347. pcll->Next = new CLinkedList ; // at the end of array, it create redundant one more CLinkedList;
  2348. pcll = pcll->Next ;
  2349. }
  2350. dwLinked = (UINT_PTR)CompareGlyphsEx(0,0,(CLinkedList* )dwLinked) ;
  2351. int size = CLinkedList::Size() ;
  2352. m_cwaWidth.RemoveAll() ;
  2353. m_cwaWidth.SetSize(m_cwaNewGlyphs.GetSize()) ;
  2354. ASSERT(size >= m_cwaNewGlyphs.GetSize() ) ;
  2355. CLinkedList* pgarbage = NULL ;
  2356. for ( pcll =(CLinkedList*) dwLinked, i = 0 ; i < m_cwaNewGlyphs.GetSize() ; i++ ,pgarbage=pcll, pcll = pcll->Next ) {
  2357. m_cwaWidth[i] = pcll->data ;
  2358. delete pgarbage;
  2359. }
  2360. m_cwaOldGlyphs.RemoveAll();
  2361. m_cwaOldGlyphs.Copy(m_cwaNewGlyphs) ;
  2362. }
  2363. else {
  2364. // Collect all the handles
  2365. m_pcgmTranslation->Collect(m_cpaGlyphs) ;
  2366. m_cwaWidth.RemoveAll() ;
  2367. if (m_cpaGlyphs.GetSize() > 0)
  2368. m_cwaWidth.InsertAt(0, 0, m_cpaGlyphs.GetSize()) ;
  2369. unsigned uWidth = (unsigned)m_cwaWidth.GetSize();
  2370. unsigned uWidthIdx ;
  2371. // Build the widths table.
  2372. for (unsigned u = 0; u < pwt->dwRunNum; u++) {
  2373. PWORD pwWidth = (PWORD) (pbwt + pwt->WidthRun[u].loCharWidthOffset) ;
  2374. unsigned uGlyph = 0 ;
  2375. for ( ; uGlyph < pwt->WidthRun[u].wGlyphCount ; uGlyph++) {
  2376. // For whatever reason, there are times when the index value is
  2377. // < 0 or > uWidth. An AV would occur if m_cwaWidth were allowed
  2378. // to be indexed by such a value. Just keep this from happening
  2379. // for now. A better fix is needed. BUG_BUG : won't fix
  2380. // Glyph handles start at 1, not 0!
  2381. uWidthIdx = uGlyph + -1 + pwt->WidthRun[u].wStartGlyph ;
  2382. if ((int) uWidthIdx < 0) {
  2383. //AfxMessageBox("Negative width table index") ;
  2384. //TRACE("***Negative width table index (%d) found in %s. Table size=%d uGlyph=%d wGlyphCount=%d wStartGlyph=%d u=%d dwRunNum=%d\n", uWidthIdx, Name(), uWidth, uGlyph, pwt->WidthRun[u].wGlyphCount, pwt->WidthRun[u].wStartGlyph, u, pwt->dwRunNum) ;
  2385. continue ;
  2386. } else if (uWidthIdx >= uWidth) {
  2387. //AfxMessageBox("Width table index (%d) > table size") ;
  2388. //TRACE("***Width table index (%d) > table size (%d) found in %s. Table size=%d uGlyph=%d wGlyphCount=%d wStartGlyph=%d u=%d dwRunNum=%d\n", uWidthIdx, uWidth, Name(), uWidth, uGlyph, pwt->WidthRun[u].wGlyphCount, pwt->WidthRun[u].wStartGlyph, u, pwt->dwRunNum) ;
  2389. break ; // rm fix VC IDE compiler problem?
  2390. } ;
  2391. //m_cwaWidth[uGlyph + -1 + pwt->WidthRun[u].wStartGlyph] = *pwWidth++; // Glyph handles start at 1, not 0!
  2392. m_cwaWidth[uWidthIdx] = *pwWidth++;
  2393. } ;
  2394. } ;
  2395. }
  2396. // The widths were successfully reloaded so update the reload time and
  2397. // return true.
  2398. m_ctReloadWidthsTimeStamp = CTime::GetCurrentTime() ;
  2399. return true ;
  2400. }
  2401. /******************************************************************************
  2402. CFontInfo::GetFirstPFM
  2403. CFontInfo::GetLastPFM
  2404. ******************************************************************************/
  2405. WORD CFontInfo::GetFirstPFM()
  2406. {
  2407. res_PFMHEADER *pPFM ;
  2408. pPFM = (res_PFMHEADER *) m_cbaPFM.GetData() ;
  2409. return ((WORD) pPFM->dfFirstChar) ;
  2410. //return ((WORD) ((res_PFMHEADER *) m_cbaPFM.GetData())->dfFirstChar) ;
  2411. }
  2412. WORD CFontInfo::GetLastPFM()
  2413. {
  2414. res_PFMHEADER *pPFM ;
  2415. pPFM = (res_PFMHEADER *) m_cbaPFM.GetData() ;
  2416. return ((WORD) pPFM->dfLastChar) ;
  2417. //return ((WORD) ((res_PFMHEADER *) m_cbaPFM.GetData())->dfLastChar) ;
  2418. }
  2419. /******************************************************************************
  2420. CFontInfoContainer class
  2421. This class encapsulates one CFontInfo structure, and is used as a document
  2422. class so we can leverage the MFC document/view architecture for editing this
  2423. information both within the contet of the driver, and as a stand-alone file.
  2424. ******************************************************************************/
  2425. IMPLEMENT_DYNCREATE(CFontInfoContainer, CDocument)
  2426. /******************************************************************************
  2427. CFontInfoContainer::CFontInfoContainer()
  2428. This constructor is used when the document is dynamically created- this will
  2429. be when the user opens an existing font file, or creates a new one.
  2430. ******************************************************************************/
  2431. CFontInfoContainer::CFontInfoContainer() {
  2432. m_bEmbedded = FALSE;
  2433. m_pcfi = new CFontInfo;
  2434. m_pcfi -> NoteOwner(*this);
  2435. }
  2436. /******************************************************************************
  2437. CFontInfoContainer::CFontInfoContainer(CFontInfo *pcfi, CString csPath) {
  2438. This constructor is called when we invoke an editing view from the driver
  2439. editor. It gives us the font information to view and the name of the file
  2440. to generate if the user decies to save the data from this view.
  2441. ******************************************************************************/
  2442. CFontInfoContainer::CFontInfoContainer(CFontInfo *pcfi, CString csPath) {
  2443. m_pcfi = pcfi;
  2444. m_bEmbedded = TRUE;
  2445. SetPathName(csPath, FALSE);
  2446. m_pcfi -> NoteOwner(*this); // Even when embedded, we're editing a file.
  2447. }
  2448. /******************************************************************************
  2449. CFontInfoContainer::OnNewDocument
  2450. This is an override- it is called when we are asked to create new font
  2451. information from scratch. For now, this will just fail.
  2452. ******************************************************************************/
  2453. BOOL CFontInfoContainer::OnNewDocument() {
  2454. // AfxMessageBox(IDS_Unimplemented); // raid 104822 temp
  2455. // return FALSE;
  2456. return m_pcfi && CDocument::OnNewDocument();// raid 104822 temp
  2457. }
  2458. /******************************************************************************
  2459. CFontInfoContainer::~CFontInfoContainer
  2460. Our erstwhile destructor must destroy the font info if this wasn't an
  2461. embedded view; ie, the UFM was loaded standalone.
  2462. It should also destroy the font's GTT iff the UFM was loaded standalone and
  2463. the GTT was based on a real, file-based GTT; not a code page loaded as a GTT
  2464. and not one of the predefined, built-in GTTs. (In the latter case, the
  2465. predefined GTTs are freed when the program exits.)
  2466. ******************************************************************************/
  2467. CFontInfoContainer::~CFontInfoContainer()
  2468. {
  2469. if (!m_bEmbedded && m_pcfi) {
  2470. int ngttid = (int) (short) m_pcfi->m_lGlyphSetDataRCID ;
  2471. if (m_pcfi->m_pcgmTranslation && ngttid != 0)
  2472. if ((ngttid < CGlyphMap::Wansung || ngttid > CGlyphMap::Big5)
  2473. && (ngttid < CGlyphMap::CodePage863 || ngttid > CGlyphMap::CodePage437)
  2474. && ngttid != -IDR_CP1252)
  2475. delete m_pcfi->m_pcgmTranslation ;
  2476. delete m_pcfi ;
  2477. } ;
  2478. }
  2479. BEGIN_MESSAGE_MAP(CFontInfoContainer, CDocument)
  2480. //{{AFX_MSG_MAP(CFontInfoContainer)
  2481. // NOTE - the ClassWizard will add and remove mapping macros here.
  2482. //}}AFX_MSG_MAP
  2483. END_MESSAGE_MAP()
  2484. /////////////////////////////////////////////////////////////////////////////
  2485. // CFontInfoContainer diagnostics
  2486. #ifdef _DEBUG
  2487. void CFontInfoContainer::AssertValid() const {
  2488. CDocument::AssertValid();
  2489. }
  2490. void CFontInfoContainer::Dump(CDumpContext& dc) const {
  2491. CDocument::Dump(dc);
  2492. }
  2493. #endif //_DEBUG
  2494. /////////////////////////////////////////////////////////////////////////////
  2495. // CFontInfoContainer serialization
  2496. void CFontInfoContainer::Serialize(CArchive& ar) {
  2497. if (ar.IsStoring()) {
  2498. // TODO: add storing code here
  2499. }
  2500. else {
  2501. // TODO: add loading code here
  2502. }
  2503. }
  2504. /////////////////////////////////////////////////////////////////////////////
  2505. // CFontInfoContainer commands
  2506. /******************************************************************************
  2507. CFontInfoContainer::SaveModified
  2508. o If the file is saved, get rid of the copy of the kerning pairs table.
  2509. Otherwise, restore the saved copy of the original kerning pairs table.
  2510. ******************************************************************************/
  2511. BOOL CFontInfoContainer::SaveModified()
  2512. {
  2513. m_UFMSaved = false ; // No save attempt made yet.
  2514. // If the file needs to be saved prompt the user about it and do it if the
  2515. // user concurs. Save the result so I can tell if the document is going
  2516. // to close.
  2517. BOOL bclose = CDocument::SaveModified() ;
  2518. // If the doc is not closing, just return bclose without doing anything
  2519. // else.
  2520. if (!bclose)
  2521. return bclose ;
  2522. // If the file was saved, the kerning table copy is no longer needed so zap
  2523. // it in a way that will free all associated memory.
  2524. if (m_UFMSaved)
  2525. m_pcfi->m_csoaKernCopy.RemoveAll() ;
  2526. // Otherwise, the user wants to revert back to the original kern copy. So,
  2527. // zap the kerning table and replace it with the copy.
  2528. else {
  2529. m_pcfi->m_csoaKern.RemoveAll() ; // This frees ALL associated memory
  2530. m_pcfi->m_csoaKern.Copy(m_pcfi->m_csoaKernCopy) ;
  2531. // Now clear the copy in a way that will not delete the class instances
  2532. // referenced by it because copies of those pointers are in m_csoaKern
  2533. // now.
  2534. CObArray* pcoacopy = m_pcfi->m_csoaKernCopy.GetCOA() ;
  2535. pcoacopy->RemoveAll() ;
  2536. } ;
  2537. // Return whatever CDocument::SaveModified() returned.
  2538. return bclose ;
  2539. }
  2540. /******************************************************************************
  2541. CFontInfoContainer::PublicSaveModified
  2542. The Class Wizard made SaveModified() a protected class and I didn't want to
  2543. change that. Instead, I added this routine so that outsiders can call it.
  2544. ******************************************************************************/
  2545. BOOL CFontInfoContainer::PublicSaveModified()
  2546. {
  2547. return (SaveModified()) ;
  2548. }
  2549. /******************************************************************************
  2550. CFontInfoContainer::OnSaveDocument
  2551. This is called in response to a Save or Save As. We pass it directly to the
  2552. CFontInfo for processing, rather than using the base class implementation,
  2553. which would serialize the document. (Actually saving the UFM is the last --
  2554. ie, final -- thing this routine does.)
  2555. Before the document is actually saved, validate the contents of the UFM. If
  2556. the UFM passes all of the checks or the user doesn't want to fix the problems,
  2557. continue processing. Otherwise, return FALSE to make sure the document is
  2558. left open.
  2559. Once the UFM has been validated, copy the data in the UFM Editor's controls
  2560. back into the CFontInfo class instance. New data is maintain in the editor
  2561. until this point so that the CFontInfo class instance is not updated
  2562. unnecessarily. That would be a problem since the UFMs are always kept
  2563. loaded in CFontInfo class instances. That means that even unsaved data that
  2564. the user wanted to discard would still be displayed the next time the UFM
  2565. is loaded into the editor. Keeping unsaved data in the editor allows it to
  2566. be discarded without affecting the CFontInfo class so the problem is avoided.
  2567. ******************************************************************************/
  2568. BOOL CFontInfoContainer::OnSaveDocument(LPCTSTR lpszPathName)
  2569. {
  2570. // Get a pointer to the associate view class instance.
  2571. POSITION pos = GetFirstViewPosition() ;
  2572. ASSERT(pos != NULL) ;
  2573. CFontViewer* pcfv = (CFontViewer*) GetNextView(pos) ;
  2574. // Call the view class to validate the UFM's contents. If one of the
  2575. // checks fails and the user wants to fix it, do not close the document.
  2576. // if rcid changed, upgraded the Widthtable.
  2577. if (m_pcfi->IsRCIDChanged() && m_bEmbedded)
  2578. pcfv->HandleCPGTTChange(true) ;
  2579. // validate the value of the UFMs
  2580. if (pcfv != NULL && pcfv->ValidateSelectedUFMDataFields())
  2581. return FALSE ;
  2582. // Update the UFM's fields with the new data in the editor.
  2583. if (pcfv != NULL && pcfv->SaveEditorDataInUFM())
  2584. return FALSE ;
  2585. m_UFMSaved = true ; // Indicate that an attempt to save will be made
  2586. return m_pcfi -> Store(lpszPathName);
  2587. }
  2588. /******************************************************************************
  2589. CFontInfoContainer::OnOpenDocument
  2590. ******************************************************************************/
  2591. BOOL CFontInfoContainer::OnOpenDocument(LPCTSTR lpstrFile)
  2592. {
  2593. // SetFileName() is just called to set a few variables. (Since the file
  2594. // exists, we don't need to do a creation check.)
  2595. m_pcfi->m_cfn.EnableCreationCheck(FALSE) ;
  2596. m_pcfi->SetFileName(lpstrFile) ;
  2597. // Load the UFM and mark it as a file that cannot be saved. That is the
  2598. // case when a UFM is loaded standalone because its associated GTT is not
  2599. // loaded too. (Some data that is saved in the UFM comes from the GTT.)
  2600. return m_pcfi->Load(false) ;
  2601. }