FFontXML_Internal.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #if !defined(USE_NULLFONT_ALWAYS)
  10. #include <AtomLyIntegration/AtomFont/FFont.h>
  11. #include <AtomLyIntegration/AtomFont/FontTexture.h>
  12. #include <CryCommon/Cry_Math.h>
  13. #include <CryCommon/CryPath.h>
  14. #include <AzCore/PlatformIncl.h>
  15. //////////////////////////////////////////////////////////////////////////
  16. // Xml parser implementation
  17. namespace AtomFontInternal
  18. {
  19. enum
  20. {
  21. ELEMENT_UNKNOWN = 0,
  22. ELEMENT_FONT = 1,
  23. ELEMENT_EFFECT = 2,
  24. ELEMENT_EFFECTFILE = 3,
  25. ELEMENT_PASS = 4,
  26. ELEMENT_PASS_COLOR = 5,
  27. ELEMENT_PASS_POSOFFSET = 12,
  28. ELEMENT_PASS_BLEND = 14
  29. };
  30. inline int GetBlendModeFromString(const AZStd::string& str, bool dst)
  31. {
  32. int blend = GS_BLSRC_ONE;
  33. if (str == "zero")
  34. {
  35. blend = dst ? GS_BLDST_ZERO : GS_BLSRC_ZERO;
  36. }
  37. else if (str == "one")
  38. {
  39. blend = dst ? GS_BLDST_ONE : GS_BLSRC_ONE;
  40. }
  41. else if (str == "srcalpha" ||
  42. str == "src_alpha")
  43. {
  44. blend = dst ? GS_BLDST_SRCALPHA : GS_BLSRC_SRCALPHA;
  45. }
  46. else if (str == "invsrcalpha" ||
  47. str == "inv_src_alpha")
  48. {
  49. blend = dst ? GS_BLDST_ONEMINUSSRCALPHA : GS_BLSRC_ONEMINUSSRCALPHA;
  50. }
  51. else if (str == "dstalpha" ||
  52. str == "dst_alpha")
  53. {
  54. blend = dst ? GS_BLDST_DSTALPHA : GS_BLSRC_DSTALPHA;
  55. }
  56. else if (str == "invdstalpha" ||
  57. str == "inv_dst_alpha")
  58. {
  59. blend = dst ? GS_BLDST_ONEMINUSDSTALPHA : GS_BLSRC_ONEMINUSDSTALPHA;
  60. }
  61. else if (str == "dstcolor" ||
  62. str == "dst_color")
  63. {
  64. blend = GS_BLSRC_DSTCOL;
  65. }
  66. else if (str == "srccolor" ||
  67. str == "src_color")
  68. {
  69. blend = GS_BLDST_SRCCOL;
  70. }
  71. else if (str == "invdstcolor" ||
  72. str == "inv_dst_color")
  73. {
  74. blend = GS_BLSRC_ONEMINUSDSTCOL;
  75. }
  76. else if (str == "invsrccolor" ||
  77. str == "inv_src_color")
  78. {
  79. blend = GS_BLDST_ONEMINUSSRCCOL;
  80. }
  81. return blend;
  82. }
  83. inline int CreateTTFFontFlag(AZ::FontSmoothMethod smoothMethod, AZ::FontSmoothAmount smoothAmount)
  84. {
  85. return (
  86. ((static_cast<int>(smoothMethod) << TTFFLAG_SMOOTH_SHIFT) & TTFFLAG_SMOOTH_MASK) |
  87. ((static_cast<int>(smoothAmount) << TTFFLAG_SMOOTH_AMOUNT_SHIFT) & TTFFLAG_SMOOTH_AMOUNT_MASK)
  88. );
  89. }
  90. inline AZ::FontSmoothMethod TranslateSmoothMethod(const AZStd::string& value)
  91. {
  92. AZ::FontSmoothMethod smoothMethod = AZ::FontSmoothMethod::None;
  93. if (value == "blur")
  94. {
  95. smoothMethod = AZ::FontSmoothMethod::Blur;
  96. }
  97. else if (value == "supersample")
  98. {
  99. smoothMethod = AZ::FontSmoothMethod::SuperSample;
  100. }
  101. return smoothMethod;
  102. }
  103. inline AZ::FontSmoothAmount TranslateSmoothAmount(int value)
  104. {
  105. AZ::FontSmoothAmount smoothAmount = AZ::FontSmoothAmount::None;
  106. if (value == 1)
  107. {
  108. smoothAmount = AZ::FontSmoothAmount::x2;
  109. }
  110. else if (value > 1)
  111. {
  112. smoothAmount = AZ::FontSmoothAmount::x4;
  113. }
  114. return smoothAmount;
  115. }
  116. class XmlFontShader
  117. {
  118. static const int DefaultSlotWidthSize = 16;
  119. static const int DefaultSlotHeightSize = 8;
  120. public:
  121. XmlFontShader(AZ::FFont* font)
  122. : m_font(font)
  123. , m_nElement(ELEMENT_UNKNOWN)
  124. , m_slotSizes(DefaultSlotWidthSize, DefaultSlotHeightSize)
  125. , m_effect(NULL)
  126. , m_pass(NULL)
  127. , m_FontTexSize(0, 0)
  128. , m_FontSmoothAmount(AZ::FontSmoothAmount::None)
  129. , m_FontSmoothMethod(AZ::FontSmoothMethod::None)
  130. {
  131. }
  132. ~XmlFontShader()
  133. {
  134. }
  135. void ScanXmlNodesRecursively(XmlNodeRef node)
  136. {
  137. if (!node)
  138. {
  139. return;
  140. }
  141. FoundElement(node->getTag());
  142. for (int i = 0, count = node->getNumAttributes(); i < count; ++i)
  143. {
  144. const char* key = "";
  145. const char* value = "";
  146. if (node->getAttributeByIndex(i, &key, &value))
  147. {
  148. FoundAttribute(key, value);
  149. }
  150. }
  151. for (int i = 0, count = node->getChildCount(); i < count; ++i)
  152. {
  153. XmlNodeRef child = node->getChild(i);
  154. ScanXmlNodesRecursively(child);
  155. }
  156. }
  157. private:
  158. void FoundElementImpl();
  159. // notify methods
  160. void FoundElement(const AZStd::string& name)
  161. {
  162. // process the previous element
  163. switch (m_nElement)
  164. {
  165. case ELEMENT_FONT:
  166. {
  167. if (!m_FontTexSize.x || !m_FontTexSize.y)
  168. {
  169. m_FontTexSize.set(512, 512);
  170. }
  171. bool fontLoaded = m_font->Load(
  172. m_strFontPath.c_str(),
  173. static_cast<unsigned int>(m_FontTexSize.x),
  174. static_cast<unsigned int>(m_FontTexSize.y),
  175. m_slotSizes.x,
  176. m_slotSizes.y,
  177. CreateTTFFontFlag(m_FontSmoothMethod, m_FontSmoothAmount),
  178. m_SizeRatio
  179. );
  180. if (!fontLoaded)
  181. {
  182. FoundElementImpl();
  183. }
  184. }
  185. break;
  186. default:
  187. break;
  188. }
  189. // Translate the m_nElement name to a define
  190. if (name == "font")
  191. {
  192. m_nElement = ELEMENT_FONT;
  193. }
  194. else if (name == "effect")
  195. {
  196. m_nElement = ELEMENT_EFFECT;
  197. }
  198. else if (name == "effectfile")
  199. {
  200. m_nElement = ELEMENT_EFFECTFILE;
  201. }
  202. else if (name == "pass")
  203. {
  204. m_pass = NULL;
  205. m_nElement = ELEMENT_PASS;
  206. if (m_effect)
  207. {
  208. m_pass = m_effect->AddPass();
  209. }
  210. }
  211. else if (name == "color")
  212. {
  213. m_nElement = ELEMENT_PASS_COLOR;
  214. }
  215. else if (name == "pos" ||
  216. name == "offset")
  217. {
  218. m_nElement = ELEMENT_PASS_POSOFFSET;
  219. }
  220. else if (name == "blend" ||
  221. name == "blending")
  222. {
  223. m_nElement = ELEMENT_PASS_BLEND;
  224. }
  225. else
  226. {
  227. m_nElement = ELEMENT_UNKNOWN;
  228. }
  229. }
  230. void FoundAttribute(const AZStd::string& name, const AZStd::string& value)
  231. {
  232. switch (m_nElement)
  233. {
  234. case ELEMENT_FONT:
  235. if (name == "path")
  236. {
  237. m_strFontPath = value;
  238. }
  239. else if (name == "w")
  240. {
  241. m_FontTexSize.x = (long)atof(value.c_str());
  242. }
  243. else if (name == "h")
  244. {
  245. m_FontTexSize.y = (long)atof(value.c_str());
  246. }
  247. else if (name == "widthslots")
  248. {
  249. m_slotSizes.x = (int)atoi(value.c_str());
  250. }
  251. else if (name == "heightslots")
  252. {
  253. m_slotSizes.y = (int)atoi(value.c_str());
  254. }
  255. else if (name == "sizeratio")
  256. {
  257. m_SizeRatio = static_cast<float>(atof(value.c_str()));
  258. }
  259. else if (name == "smooth")
  260. {
  261. m_FontSmoothMethod = TranslateSmoothMethod(value);
  262. }
  263. else if (name == "smooth_amount")
  264. {
  265. m_FontSmoothAmount = TranslateSmoothAmount((int)atof(value.c_str()));
  266. }
  267. break;
  268. case ELEMENT_EFFECT:
  269. if (name == "name")
  270. {
  271. if (value == "default")
  272. {
  273. m_effect = m_font->GetDefaultEffect();
  274. m_effect->ClearPasses();
  275. }
  276. else
  277. {
  278. m_effect = m_font->AddEffect(value.c_str());
  279. }
  280. }
  281. break;
  282. case ELEMENT_EFFECTFILE:
  283. if (name == "path")
  284. {
  285. m_strFontEffectPath = value;
  286. }
  287. break;
  288. case ELEMENT_PASS_COLOR:
  289. if (!m_pass)
  290. {
  291. break;
  292. }
  293. if (name == "r")
  294. {
  295. m_pass->m_color.r = (uint8_t)((float)atof(value.c_str()) * 255.0f);
  296. }
  297. else if (name == "g")
  298. {
  299. m_pass->m_color.g = (uint8_t)((float)atof(value.c_str()) * 255.0f);
  300. }
  301. else if (name == "b")
  302. {
  303. m_pass->m_color.b = (uint8_t)((float)atof(value.c_str()) * 255.0f);
  304. }
  305. else if (name == "a")
  306. {
  307. m_pass->m_color.a = (uint8_t)((float)atof(value.c_str()) * 255.0f);
  308. }
  309. break;
  310. case ELEMENT_PASS_POSOFFSET:
  311. if (!m_pass)
  312. {
  313. break;
  314. }
  315. if (name == "x")
  316. {
  317. m_pass->m_posOffset.x = (float)atoi(value.c_str());
  318. }
  319. else if (name == "y")
  320. {
  321. m_pass->m_posOffset.y = (float)atoi(value.c_str());
  322. }
  323. break;
  324. case ELEMENT_PASS_BLEND:
  325. if (!m_pass)
  326. {
  327. break;
  328. }
  329. if (name == "src")
  330. {
  331. m_pass->m_blendSrc = GetBlendModeFromString(value, false);
  332. }
  333. else if (name == "dst")
  334. {
  335. m_pass->m_blendDest = GetBlendModeFromString(value, true);
  336. }
  337. else if (name == "type")
  338. {
  339. if (value == "modulate")
  340. {
  341. m_pass->m_blendSrc = GS_BLSRC_SRCALPHA;
  342. m_pass->m_blendDest = GS_BLDST_ONEMINUSSRCALPHA;
  343. }
  344. else if (value == "additive")
  345. {
  346. m_pass->m_blendSrc = GS_BLSRC_SRCALPHA;
  347. m_pass->m_blendDest = GS_BLDST_ONE;
  348. }
  349. }
  350. break;
  351. default:
  352. case ELEMENT_UNKNOWN:
  353. break;
  354. }
  355. }
  356. public:
  357. AZ::FFont* m_font;
  358. unsigned long m_nElement;
  359. AZ::FFont::FontEffect* m_effect;
  360. AZ::FFont::FontRenderingPass* m_pass;
  361. AZStd::string m_strFontPath;
  362. AZStd::string m_strFontEffectPath;
  363. vector2l m_FontTexSize;
  364. AZ::AtomFont::GlyphSize m_slotSizes;
  365. float m_SizeRatio = IFFontConstants::defaultSizeRatio;
  366. AZ::FontSmoothMethod m_FontSmoothMethod;
  367. AZ::FontSmoothAmount m_FontSmoothAmount;
  368. };
  369. }
  370. #endif