Function.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  1. /*
  2. * Copyright (c) 2023, Nico Weber <thakis@chromium.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/NonnullOwnPtr.h>
  7. #include <LibPDF/CommonNames.h>
  8. #include <LibPDF/Document.h>
  9. #include <LibPDF/Function.h>
  10. #include <LibPDF/ObjectDerivatives.h>
  11. // PDF 1.7 spec, 3.9 Functions
  12. namespace PDF {
  13. struct Bound {
  14. float lower;
  15. float upper;
  16. };
  17. class SampledFunction final : public Function {
  18. public:
  19. virtual PDFErrorOr<ReadonlySpan<float>> evaluate(ReadonlySpan<float>) const override;
  20. };
  21. PDFErrorOr<ReadonlySpan<float>> SampledFunction::evaluate(ReadonlySpan<float>) const
  22. {
  23. return Error(Error::Type::RenderingUnsupported, "SampledFunction not yet implemented"_string);
  24. }
  25. // 3.9.2 Type 2 (Exponential Interpolation) Functions
  26. class ExponentialInterpolationFunction final : public Function {
  27. public:
  28. static PDFErrorOr<NonnullRefPtr<ExponentialInterpolationFunction>> create(Document*, Vector<Bound> domain, Optional<Vector<Bound>> range, NonnullRefPtr<DictObject>);
  29. virtual PDFErrorOr<ReadonlySpan<float>> evaluate(ReadonlySpan<float>) const override;
  30. private:
  31. Bound m_domain;
  32. Optional<Vector<Bound>> m_range;
  33. Vector<float> m_c0;
  34. Vector<float> m_c1;
  35. float m_n;
  36. Vector<float> mutable m_values;
  37. };
  38. PDFErrorOr<NonnullRefPtr<ExponentialInterpolationFunction>>
  39. ExponentialInterpolationFunction::create(Document* document, Vector<Bound> domain, Optional<Vector<Bound>> range, NonnullRefPtr<DictObject> function_dict)
  40. {
  41. if (domain.size() != 1)
  42. return Error { Error::Type::MalformedPDF, "Function exponential requires domain with 1 entry" };
  43. // "TABLE 3.37 Additional entries specific to a type 2 function dictionary"
  44. if (!function_dict->contains(CommonNames::N))
  45. return Error { Error::Type::MalformedPDF, "Function exponential requires /N" };
  46. auto n = TRY(document->resolve(function_dict->get_value(CommonNames::N))).to_float();
  47. Vector<float> c0;
  48. if (function_dict->contains(CommonNames::C0)) {
  49. auto c0_array = TRY(function_dict->get_array(document, CommonNames::C0));
  50. for (size_t i = 0; i < c0_array->size(); i++)
  51. c0.append(c0_array->at(i).to_float());
  52. } else {
  53. c0.append(0.0f);
  54. }
  55. Vector<float> c1;
  56. if (function_dict->contains(CommonNames::C1)) {
  57. auto c1_array = TRY(function_dict->get_array(document, CommonNames::C1));
  58. for (size_t i = 0; i < c1_array->size(); i++)
  59. c1.append(c1_array->at(i).to_float());
  60. } else {
  61. c1.append(1.0f);
  62. }
  63. if (c0.size() != c1.size())
  64. return Error { Error::Type::MalformedPDF, "Function exponential mismatching C0 and C1 arrays" };
  65. if (range.has_value()) {
  66. if (range->size() != c0.size())
  67. return Error { Error::Type::MalformedPDF, "Function exponential mismatching Range and C arrays" };
  68. }
  69. // "Values of Domain must constrain x in such a way that if N is not an integer,
  70. // all values of x must be non-negative, and if N is negative, no value of x may be zero."
  71. if (n != (int)n && domain[0].lower < 0)
  72. return Error { Error::Type::MalformedPDF, "Function exponential requires non-negative bound for non-integer N" };
  73. if (n < 0 && (domain[0].lower <= 0 && domain[0].upper >= 0))
  74. return Error { Error::Type::MalformedPDF, "Function exponential with negative N requires non-zero domain" };
  75. auto function = adopt_ref(*new ExponentialInterpolationFunction());
  76. function->m_domain = domain[0];
  77. function->m_range = move(range);
  78. function->m_c0 = move(c0);
  79. function->m_c1 = move(c1);
  80. function->m_n = n;
  81. function->m_values.resize(function->m_c0.size());
  82. return function;
  83. }
  84. PDFErrorOr<ReadonlySpan<float>> ExponentialInterpolationFunction::evaluate(ReadonlySpan<float> xs) const
  85. {
  86. if (xs.size() != 1)
  87. return Error { Error::Type::MalformedPDF, "Function argument size does not match domain size" };
  88. float const x = clamp(xs[0], m_domain.lower, m_domain.upper);
  89. for (size_t i = 0; i < m_c0.size(); ++i)
  90. m_values[i] = m_c0[i] + pow(x, m_n) * (m_c1[i] - m_c0[i]);
  91. if (m_range.has_value()) {
  92. for (size_t i = 0; i < m_c0.size(); ++i)
  93. m_values[i] = clamp(m_values[i], m_range.value()[i].lower, m_range.value()[i].upper);
  94. }
  95. return m_values;
  96. }
  97. class StitchingFunction final : public Function {
  98. public:
  99. static PDFErrorOr<NonnullRefPtr<StitchingFunction>> create(Document*, Vector<Bound> domain, Optional<Vector<Bound>> range, NonnullRefPtr<DictObject>);
  100. virtual PDFErrorOr<ReadonlySpan<float>> evaluate(ReadonlySpan<float>) const override;
  101. private:
  102. StitchingFunction(Vector<NonnullRefPtr<Function>>);
  103. Bound m_domain;
  104. Optional<Vector<Bound>> m_range;
  105. Vector<NonnullRefPtr<Function>> m_functions;
  106. Vector<float> m_bounds;
  107. Vector<Bound> m_encode;
  108. Vector<float> mutable m_result;
  109. };
  110. StitchingFunction::StitchingFunction(Vector<NonnullRefPtr<Function>> functions)
  111. : m_functions(move(functions))
  112. {
  113. }
  114. PDFErrorOr<NonnullRefPtr<StitchingFunction>>
  115. StitchingFunction::create(Document* document, Vector<Bound> domain, Optional<Vector<Bound>> range, NonnullRefPtr<DictObject> dict)
  116. {
  117. if (domain.size() != 1)
  118. return Error { Error::Type::MalformedPDF, "Function stitching requires domain with 1 entry" };
  119. // "TABLE 3.38 Additional entries specific to a type 3 function dictionary"
  120. if (!dict->contains(CommonNames::Functions))
  121. return Error { Error::Type::MalformedPDF, "Function stitching requires /Functions" };
  122. auto functions_array = TRY(dict->get_array(document, CommonNames::Functions));
  123. Vector<NonnullRefPtr<Function>> functions;
  124. for (size_t i = 0; i < functions_array->size(); i++) {
  125. auto function = TRY(Function::create(document, functions_array->get_object_at(i)));
  126. functions.append(move(function));
  127. }
  128. if (functions.is_empty())
  129. return Error { Error::Type::MalformedPDF, "Function stitching requires at least one function" };
  130. if (!dict->contains(CommonNames::Bounds))
  131. return Error { Error::Type::MalformedPDF, "Function stitching requires /Bounds" };
  132. auto bounds_array = TRY(dict->get_array(document, CommonNames::Bounds));
  133. if (bounds_array->size() != functions.size() - 1)
  134. return Error { Error::Type::MalformedPDF, "Function stitching /Bounds size does not match /Functions size" };
  135. Vector<float> bounds;
  136. for (size_t i = 0; i < bounds_array->size(); i++) {
  137. bounds.append(bounds_array->at(i).to_float());
  138. if (i > 0 && bounds[i - 1] >= bounds[i])
  139. return Error { Error::Type::MalformedPDF, "Function stitching /Bounds not strictly increasing" };
  140. }
  141. if (!bounds.is_empty()) {
  142. if (domain[0].lower == domain[0].upper)
  143. return Error { Error::Type::MalformedPDF, "Function stitching /Bounds requires non-zero domain" };
  144. if (domain[0].lower >= bounds[0] || bounds.last() >= domain[0].upper)
  145. return Error { Error::Type::MalformedPDF, "Function stitching /Bounds out of domain" };
  146. }
  147. if (!dict->contains(CommonNames::Encode))
  148. return Error { Error::Type::MalformedPDF, "Function stitching requires /Encode" };
  149. auto encode_array = TRY(dict->get_array(document, CommonNames::Encode));
  150. if (encode_array->size() != functions.size() * 2)
  151. return Error { Error::Type::MalformedPDF, "Function stitching /Encode size does not match /Functions size" };
  152. Vector<Bound> encode;
  153. for (size_t i = 0; i < encode_array->size(); i += 2) {
  154. encode.append({ encode_array->at(i).to_float(), encode_array->at(i + 1).to_float() });
  155. if (encode.last().lower > encode.last().upper)
  156. return Error { Error::Type::MalformedPDF, "Function stitching /Encode lower bound > upper bound" };
  157. }
  158. auto function = adopt_ref(*new StitchingFunction(move(functions)));
  159. function->m_domain = domain[0];
  160. function->m_range = move(range);
  161. function->m_bounds = move(bounds);
  162. function->m_encode = move(encode);
  163. if (function->m_range.has_value())
  164. function->m_result.resize(function->m_range.value().size());
  165. return function;
  166. }
  167. PDFErrorOr<ReadonlySpan<float>> StitchingFunction::evaluate(ReadonlySpan<float>) const
  168. {
  169. return Error(Error::Type::RenderingUnsupported, "StitchingFunction not yet implemented"_string);
  170. }
  171. class PostScriptCalculatorFunction final : public Function {
  172. public:
  173. static PDFErrorOr<NonnullRefPtr<PostScriptCalculatorFunction>> create(Vector<Bound> domain, Optional<Vector<Bound>> range, NonnullRefPtr<StreamObject>);
  174. virtual PDFErrorOr<ReadonlySpan<float>> evaluate(ReadonlySpan<float>) const override;
  175. private:
  176. // TABLE 3.39 Operators in type 4 functions
  177. enum class OperatorType {
  178. Operand,
  179. // Arithmetic operators
  180. Abs,
  181. Add,
  182. Atan,
  183. Ceiling,
  184. Cos,
  185. Cvi,
  186. Cvr,
  187. Div,
  188. Exp,
  189. Floor,
  190. Idiv,
  191. Ln,
  192. Log,
  193. Mod,
  194. Mul,
  195. Neg,
  196. Round,
  197. Sin,
  198. Sqrt,
  199. Sub,
  200. Truncate,
  201. // Relational, boolean, and bitwise operators
  202. And,
  203. Bitshift,
  204. Eq,
  205. False,
  206. Ge,
  207. Gt,
  208. Le,
  209. Lt,
  210. Ne,
  211. Not,
  212. Or,
  213. True,
  214. Xor,
  215. // Conditional operators
  216. If,
  217. IfElse,
  218. // Stack operators
  219. Copy,
  220. Dup,
  221. Exch,
  222. Index,
  223. Pop,
  224. Roll,
  225. };
  226. static Optional<OperatorType> parse_operator(Reader&);
  227. struct IfElse;
  228. struct Token {
  229. // FIXME: Could nan-box this.
  230. OperatorType type;
  231. Variant<Empty, float, int> value {};
  232. };
  233. struct IfElse {
  234. Vector<Token> if_true;
  235. Vector<Token> if_false;
  236. };
  237. static PDFErrorOr<Vector<Token>> parse_postscript_calculator_function(Reader&, Vector<NonnullOwnPtr<IfElse>>&);
  238. struct Stack {
  239. Array<float, 100> stack;
  240. size_t top { 0 };
  241. PDFErrorOr<void> push(float value)
  242. {
  243. if (top == stack.size())
  244. return Error { Error::Type::RenderingUnsupported, "PostScript stack overflow"_string };
  245. stack[top++] = value;
  246. return {};
  247. }
  248. PDFErrorOr<float> pop()
  249. {
  250. if (top == 0)
  251. return Error { Error::Type::RenderingUnsupported, "PostScript stack underflow"_string };
  252. return stack[--top];
  253. }
  254. };
  255. PDFErrorOr<void> execute(Vector<Token> const&, Stack&) const;
  256. Vector<Bound> m_domain;
  257. Vector<Bound> m_range;
  258. Vector<Token> m_tokens;
  259. Vector<NonnullOwnPtr<IfElse>> m_if_elses;
  260. Vector<float> mutable m_result;
  261. };
  262. Optional<PostScriptCalculatorFunction::OperatorType> PostScriptCalculatorFunction::parse_operator(Reader& reader)
  263. {
  264. auto match_keyword = [&](char const* keyword) {
  265. if (reader.matches(keyword)) {
  266. reader.consume((int)strlen(keyword));
  267. return true;
  268. }
  269. return false;
  270. };
  271. if (match_keyword("abs"))
  272. return OperatorType::Abs;
  273. if (match_keyword("add"))
  274. return OperatorType::Add;
  275. if (match_keyword("atan"))
  276. return OperatorType::Atan;
  277. if (match_keyword("ceiling"))
  278. return OperatorType::Ceiling;
  279. if (match_keyword("cos"))
  280. return OperatorType::Cos;
  281. if (match_keyword("cvi"))
  282. return OperatorType::Cvi;
  283. if (match_keyword("cvr"))
  284. return OperatorType::Cvr;
  285. if (match_keyword("div"))
  286. return OperatorType::Div;
  287. if (match_keyword("exp"))
  288. return OperatorType::Exp;
  289. if (match_keyword("floor"))
  290. return OperatorType::Floor;
  291. if (match_keyword("idiv"))
  292. return OperatorType::Idiv;
  293. if (match_keyword("ln"))
  294. return OperatorType::Ln;
  295. if (match_keyword("log"))
  296. return OperatorType::Log;
  297. if (match_keyword("mod"))
  298. return OperatorType::Mod;
  299. if (match_keyword("mul"))
  300. return OperatorType::Mul;
  301. if (match_keyword("neg"))
  302. return OperatorType::Neg;
  303. if (match_keyword("round"))
  304. return OperatorType::Round;
  305. if (match_keyword("sin"))
  306. return OperatorType::Sin;
  307. if (match_keyword("sqrt"))
  308. return OperatorType::Sqrt;
  309. if (match_keyword("sub"))
  310. return OperatorType::Sub;
  311. if (match_keyword("truncate"))
  312. return OperatorType::Truncate;
  313. if (match_keyword("and"))
  314. return OperatorType::And;
  315. if (match_keyword("bitshift"))
  316. return OperatorType::Bitshift;
  317. if (match_keyword("eq"))
  318. return OperatorType::Eq;
  319. if (match_keyword("false"))
  320. return OperatorType::False;
  321. if (match_keyword("ge"))
  322. return OperatorType::Ge;
  323. if (match_keyword("gt"))
  324. return OperatorType::Gt;
  325. if (match_keyword("le"))
  326. return OperatorType::Le;
  327. if (match_keyword("lt"))
  328. return OperatorType::Lt;
  329. if (match_keyword("ne"))
  330. return OperatorType::Ne;
  331. if (match_keyword("not"))
  332. return OperatorType::Not;
  333. if (match_keyword("or"))
  334. return OperatorType::Or;
  335. if (match_keyword("true"))
  336. return OperatorType::True;
  337. if (match_keyword("xor"))
  338. return OperatorType::Xor;
  339. // If and Ifelse handled elsewhere.
  340. if (match_keyword("copy"))
  341. return OperatorType::Copy;
  342. if (match_keyword("dup"))
  343. return OperatorType::Dup;
  344. if (match_keyword("exch"))
  345. return OperatorType::Exch;
  346. if (match_keyword("index"))
  347. return OperatorType::Index;
  348. if (match_keyword("pop"))
  349. return OperatorType::Pop;
  350. if (match_keyword("roll"))
  351. return OperatorType::Roll;
  352. return {};
  353. }
  354. PDFErrorOr<Vector<PostScriptCalculatorFunction::Token>>
  355. PostScriptCalculatorFunction::parse_postscript_calculator_function(Reader& reader, Vector<NonnullOwnPtr<IfElse>>& if_elses)
  356. {
  357. // Assumes valid syntax.
  358. reader.consume_whitespace();
  359. if (!reader.consume('{'))
  360. return Error { Error::Type::MalformedPDF, "PostScript expected '{'" };
  361. Vector<PostScriptCalculatorFunction::Token> tokens;
  362. while (!reader.matches('}')) {
  363. if (reader.consume_whitespace())
  364. continue;
  365. if (reader.matches('{')) {
  366. auto if_true = TRY(parse_postscript_calculator_function(reader, if_elses));
  367. reader.consume_whitespace();
  368. if (reader.matches("if")) {
  369. reader.consume(2);
  370. tokens.append({ OperatorType::If, (int)if_elses.size() });
  371. if_elses.append(adopt_own(*new IfElse { move(if_true), {} }));
  372. continue;
  373. }
  374. VERIFY(reader.matches('{'));
  375. auto if_false = TRY(parse_postscript_calculator_function(reader, if_elses));
  376. reader.consume_whitespace();
  377. if (reader.matches("ifelse")) {
  378. reader.consume(6);
  379. tokens.append({ OperatorType::IfElse, (int)if_elses.size() });
  380. if_elses.append(adopt_own(*new IfElse { move(if_true), move(if_false) }));
  381. continue;
  382. }
  383. return Error { Error::Type::MalformedPDF, "PostScript confused parsing {}-delimited expressions"_string };
  384. }
  385. if (reader.matches_number()) {
  386. // FIXME: Nicer float conversion.
  387. char const* start = reinterpret_cast<char const*>(reader.bytes().slice(reader.offset()).data());
  388. char* endptr;
  389. float value = strtof(start, &endptr);
  390. reader.move_by(endptr - start);
  391. tokens.append({ OperatorType::Operand, value });
  392. continue;
  393. }
  394. if (Optional<OperatorType> op = parse_operator(reader); op.has_value()) {
  395. tokens.append({ op.value() });
  396. continue;
  397. }
  398. return Error { Error::Type::MalformedPDF, "PostScript unknown operator"_string };
  399. }
  400. VERIFY(reader.consume('}'));
  401. return tokens;
  402. }
  403. PDFErrorOr<NonnullRefPtr<PostScriptCalculatorFunction>>
  404. PostScriptCalculatorFunction::create(Vector<Bound> domain, Optional<Vector<Bound>> range, NonnullRefPtr<StreamObject> stream)
  405. {
  406. if (!range.has_value())
  407. return Error { Error::Type::MalformedPDF, "Function type 4 requires /Range" };
  408. Vector<NonnullOwnPtr<IfElse>> if_elses;
  409. Reader reader { stream->bytes() };
  410. auto tokens = TRY(parse_postscript_calculator_function(reader, if_elses));
  411. auto function = adopt_ref(*new PostScriptCalculatorFunction());
  412. function->m_domain = move(domain);
  413. function->m_range = move(range.value());
  414. function->m_tokens = move(tokens);
  415. function->m_if_elses = move(if_elses);
  416. return function;
  417. }
  418. PDFErrorOr<void> PostScriptCalculatorFunction::execute(Vector<Token> const& tokens, Stack& stack) const
  419. {
  420. for (auto const& token : tokens) {
  421. switch (token.type) {
  422. case OperatorType::Operand:
  423. TRY(stack.push(token.value.get<float>()));
  424. break;
  425. case OperatorType::Abs:
  426. TRY(stack.push(fabsf(TRY(stack.pop()))));
  427. break;
  428. case OperatorType::Add: {
  429. float b = TRY(stack.pop());
  430. float a = TRY(stack.pop());
  431. TRY(stack.push(a + b));
  432. break;
  433. }
  434. case OperatorType::Atan: {
  435. float b = TRY(stack.pop());
  436. float a = TRY(stack.pop());
  437. TRY(stack.push(AK::to_degrees(atan2f(b, a))));
  438. break;
  439. }
  440. case OperatorType::Ceiling:
  441. TRY(stack.push(ceilf(TRY(stack.pop()))));
  442. break;
  443. case OperatorType::Cos:
  444. TRY(stack.push(cosf(AK::to_radians(TRY(stack.pop())))));
  445. break;
  446. case OperatorType::Cvi:
  447. TRY(stack.push((int)TRY(stack.pop())));
  448. break;
  449. case OperatorType::Cvr:
  450. TRY(stack.push(TRY(stack.pop())));
  451. break;
  452. case OperatorType::Div: {
  453. float b = TRY(stack.pop());
  454. float a = TRY(stack.pop());
  455. TRY(stack.push(a / b));
  456. break;
  457. }
  458. case OperatorType::Exp:
  459. TRY(stack.push(expf(TRY(stack.pop()))));
  460. break;
  461. case OperatorType::Floor:
  462. TRY(stack.push(floorf(TRY(stack.pop()))));
  463. break;
  464. case OperatorType::Idiv: {
  465. int b = (int)TRY(stack.pop());
  466. int a = (int)TRY(stack.pop());
  467. TRY(stack.push(a / b));
  468. break;
  469. }
  470. case OperatorType::Ln:
  471. TRY(stack.push(logf(TRY(stack.pop()))));
  472. break;
  473. case OperatorType::Log:
  474. TRY(stack.push(log10f(TRY(stack.pop()))));
  475. break;
  476. case OperatorType::Mod: {
  477. float b = TRY(stack.pop());
  478. float a = TRY(stack.pop());
  479. TRY(stack.push(fmodf(a, b)));
  480. break;
  481. }
  482. case OperatorType::Mul: {
  483. float b = TRY(stack.pop());
  484. float a = TRY(stack.pop());
  485. TRY(stack.push(a * b));
  486. break;
  487. }
  488. case OperatorType::Neg:
  489. TRY(stack.push(-TRY(stack.pop())));
  490. break;
  491. case OperatorType::Round:
  492. TRY(stack.push(roundf(TRY(stack.pop()))));
  493. break;
  494. case OperatorType::Sin:
  495. TRY(stack.push(sinf(AK::to_radians(TRY(stack.pop())))));
  496. break;
  497. case OperatorType::Sqrt:
  498. TRY(stack.push(sqrtf(TRY(stack.pop()))));
  499. break;
  500. case OperatorType::Sub: {
  501. float b = TRY(stack.pop());
  502. float a = TRY(stack.pop());
  503. TRY(stack.push(a - b));
  504. break;
  505. }
  506. case OperatorType::Truncate:
  507. TRY(stack.push(truncf(TRY(stack.pop()))));
  508. break;
  509. case OperatorType::And: {
  510. int b = (int)TRY(stack.pop());
  511. int a = (int)TRY(stack.pop());
  512. TRY(stack.push(a & b));
  513. break;
  514. }
  515. case OperatorType::Bitshift: {
  516. int b = (int)TRY(stack.pop());
  517. int a = (int)TRY(stack.pop());
  518. if (b >= 0)
  519. TRY(stack.push(a << b));
  520. else
  521. TRY(stack.push(a >> -b));
  522. break;
  523. }
  524. case OperatorType::Eq: {
  525. float b = TRY(stack.pop());
  526. float a = TRY(stack.pop());
  527. TRY(stack.push(a == b ? 1.0f : 0.0f));
  528. break;
  529. }
  530. case OperatorType::False:
  531. TRY(stack.push(0.0f));
  532. break;
  533. case OperatorType::Ge: {
  534. float b = TRY(stack.pop());
  535. float a = TRY(stack.pop());
  536. TRY(stack.push(a >= b ? 1.0f : 0.0f));
  537. break;
  538. }
  539. case OperatorType::Gt: {
  540. float b = TRY(stack.pop());
  541. float a = TRY(stack.pop());
  542. TRY(stack.push(a > b ? 1.0f : 0.0f));
  543. break;
  544. }
  545. case OperatorType::Le: {
  546. float b = TRY(stack.pop());
  547. float a = TRY(stack.pop());
  548. TRY(stack.push(a <= b ? 1.0f : 0.0f));
  549. break;
  550. }
  551. case OperatorType::Lt: {
  552. float b = TRY(stack.pop());
  553. float a = TRY(stack.pop());
  554. TRY(stack.push(a < b ? 1.0f : 0.0f));
  555. break;
  556. }
  557. case OperatorType::Ne: {
  558. float b = TRY(stack.pop());
  559. float a = TRY(stack.pop());
  560. TRY(stack.push(a != b ? 1.0f : 0.0f));
  561. break;
  562. }
  563. case OperatorType::Not: {
  564. TRY(stack.push(TRY(stack.pop()) == 0.0f ? 1.0f : 0.0f));
  565. break;
  566. }
  567. case OperatorType::Or: {
  568. int b = (int)TRY(stack.pop());
  569. int a = (int)TRY(stack.pop());
  570. TRY(stack.push(a | b));
  571. break;
  572. }
  573. case OperatorType::True:
  574. TRY(stack.push(1.0f));
  575. break;
  576. case OperatorType::Xor: {
  577. int b = (int)TRY(stack.pop());
  578. int a = (int)TRY(stack.pop());
  579. TRY(stack.push(a ^ b));
  580. break;
  581. }
  582. case OperatorType::If: {
  583. auto const& if_else = m_if_elses[token.value.get<int>()];
  584. VERIFY(if_else->if_false.is_empty());
  585. if (TRY(stack.pop()) != 0.0f)
  586. TRY(execute(if_else->if_true, stack));
  587. break;
  588. }
  589. case OperatorType::IfElse: {
  590. auto const& if_else = m_if_elses[token.value.get<int>()];
  591. if (TRY(stack.pop()) != 0.0f)
  592. TRY(execute(if_else->if_true, stack));
  593. else
  594. TRY(execute(if_else->if_false, stack));
  595. break;
  596. }
  597. case OperatorType::Copy: {
  598. int n = (int)TRY(stack.pop());
  599. if (n < 0)
  600. return Error { Error::Type::RenderingUnsupported, "PostScript copy with negative argument"_string };
  601. if ((size_t)n > stack.top)
  602. return Error { Error::Type::RenderingUnsupported, "PostScript copy with argument larger than stack"_string };
  603. for (int i = 0; i < n; ++i)
  604. TRY(stack.push(stack.stack[stack.top - n]));
  605. break;
  606. }
  607. case OperatorType::Dup:
  608. TRY(stack.push(stack.stack[stack.top - 1]));
  609. break;
  610. case OperatorType::Exch: {
  611. float b = TRY(stack.pop());
  612. float a = TRY(stack.pop());
  613. TRY(stack.push(b));
  614. TRY(stack.push(a));
  615. break;
  616. }
  617. case OperatorType::Index: {
  618. int i = (int)TRY(stack.pop());
  619. if (i < 0)
  620. return Error { Error::Type::RenderingUnsupported, "PostScript index with negative argument"_string };
  621. if ((size_t)i >= stack.top)
  622. return Error { Error::Type::RenderingUnsupported, "PostScript index with argument larger than stack"_string };
  623. TRY(stack.push(stack.stack[stack.top - 1 - i]));
  624. break;
  625. }
  626. case OperatorType::Pop:
  627. TRY(stack.pop());
  628. break;
  629. case OperatorType::Roll: {
  630. int j = -(int)TRY(stack.pop());
  631. int n = (int)TRY(stack.pop());
  632. if (n < 0)
  633. return Error { Error::Type::RenderingUnsupported, "PostScript roll with negative argument"_string };
  634. if ((size_t)n > stack.top)
  635. return Error { Error::Type::RenderingUnsupported, "PostScript roll with argument larger than stack"_string };
  636. if (j < 0)
  637. j += n;
  638. if (j < 0)
  639. return Error { Error::Type::RenderingUnsupported, "PostScript roll with negative argument"_string };
  640. if (j > n)
  641. return Error { Error::Type::RenderingUnsupported, "PostScript roll with argument larger than stack"_string };
  642. // http://pointer-overloading.blogspot.com/2013/09/algorithms-rotating-one-dimensional.html
  643. auto elements = stack.stack.span().slice(stack.top - n, n);
  644. elements.slice(0, j).reverse();
  645. elements.slice(j).reverse();
  646. elements.reverse();
  647. break;
  648. }
  649. }
  650. }
  651. return {};
  652. }
  653. PDFErrorOr<ReadonlySpan<float>> PostScriptCalculatorFunction::evaluate(ReadonlySpan<float> xs) const
  654. {
  655. if (xs.size() != m_domain.size())
  656. return Error { Error::Type::MalformedPDF, "Function argument size does not match domain size" };
  657. Stack stack;
  658. for (size_t i = 0; i < xs.size(); ++i)
  659. TRY(stack.push(clamp(xs[i], m_domain[i].lower, m_domain[i].upper)));
  660. TRY(execute(m_tokens, stack));
  661. if (stack.top != m_range.size())
  662. return Error { Error::Type::MalformedPDF, "Postscript result size does not match range size"_string };
  663. // FIXME: Does this need reversing?
  664. m_result.resize(stack.top);
  665. for (size_t i = 0; i < stack.top; ++i)
  666. m_result[i] = clamp(stack.stack[i], m_range[i].lower, m_range[i].upper);
  667. return m_result;
  668. }
  669. PDFErrorOr<NonnullRefPtr<Function>> Function::create(Document* document, NonnullRefPtr<Object> object)
  670. {
  671. if (!object->is<DictObject>() && !object->is<StreamObject>())
  672. return Error { Error::Type::MalformedPDF, "Function object must be dict or stream" };
  673. auto function_dict = object->is<DictObject>() ? object->cast<DictObject>() : object->cast<StreamObject>()->dict();
  674. // "TABLE 3.35 Entries common to all function dictionaries"
  675. if (!function_dict->contains(CommonNames::FunctionType))
  676. return Error { Error::Type::MalformedPDF, "Function requires /FunctionType" };
  677. auto function_type = TRY(document->resolve_to<int>(function_dict->get_value(CommonNames::FunctionType)));
  678. if (!function_dict->contains(CommonNames::Domain))
  679. return Error { Error::Type::MalformedPDF, "Function requires /Domain" };
  680. auto domain_array = TRY(function_dict->get_array(document, CommonNames::Domain));
  681. if (domain_array->size() % 2 != 0)
  682. return Error { Error::Type::MalformedPDF, "Function /Domain size not multiple of 2" };
  683. Vector<Bound> domain;
  684. for (size_t i = 0; i < domain_array->size(); i += 2) {
  685. domain.append({ domain_array->at(i).to_float(), domain_array->at(i + 1).to_float() });
  686. if (domain.last().lower > domain.last().upper)
  687. return Error { Error::Type::MalformedPDF, "Function /Domain lower bound > upper bound" };
  688. }
  689. // Can't use PDFErrorOr with Optional::map()
  690. Optional<Vector<Bound>> optional_range;
  691. if (function_dict->contains(CommonNames::Range)) {
  692. auto range_array = TRY(function_dict->get_array(document, CommonNames::Range));
  693. if (range_array->size() % 2 != 0)
  694. return Error { Error::Type::MalformedPDF, "Function /Range size not multiple of 2" };
  695. Vector<Bound> range;
  696. for (size_t i = 0; i < range_array->size(); i += 2) {
  697. range.append({ range_array->at(i).to_float(), range_array->at(i + 1).to_float() });
  698. if (range.last().lower > range.last().upper)
  699. return Error { Error::Type::MalformedPDF, "Function /Range lower bound > upper bound" };
  700. }
  701. optional_range = move(range);
  702. }
  703. switch (function_type) {
  704. case 0:
  705. return adopt_ref(*new SampledFunction());
  706. // The spec has no entry for `1`.
  707. case 2:
  708. // FIXME: spec is not clear on if this should work with a StreamObject.
  709. return ExponentialInterpolationFunction::create(document, move(domain), move(optional_range), function_dict);
  710. case 3:
  711. // FIXME: spec is not clear on if this should work with a StreamObject.
  712. return StitchingFunction::create(document, move(domain), move(optional_range), function_dict);
  713. case 4:
  714. if (!object->is<StreamObject>())
  715. return Error { Error::Type::MalformedPDF, "Function type 4 requires stream object" };
  716. return PostScriptCalculatorFunction::create(move(domain), move(optional_range), object->cast<StreamObject>());
  717. default:
  718. dbgln("invalid function type {}", function_type);
  719. return Error(Error::Type::MalformedPDF, "Function has unkonwn type"_string);
  720. }
  721. }
  722. }