PdfObject.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #include "PdfObject.h"
  2. #include "MuException.h"
  3. #include "Vcclr.h"
  4. #pragma region pdf-object.c
  5. typedef enum pdf_objkind_e {
  6. PDF_INT = 'i',
  7. PDF_REAL = 'f',
  8. PDF_STRING = 's',
  9. PDF_NAME = 'n',
  10. PDF_ARRAY = 'a',
  11. PDF_DICT = 'd',
  12. PDF_INDIRECT = 'r'
  13. } pdf_objkind;
  14. #pragma endregion
  15. using namespace System;
  16. using namespace System::Runtime::InteropServices;
  17. using namespace MuPDF;
  18. // hack: this method hacks into mupdf/pdf-object.c and provides direct type kind info of a PdfObject
  19. Kind PdfObject::TypeKind::get() {
  20. if (_obj == PDF_NULL) {
  21. return Kind::Null;
  22. }
  23. if (_obj == PDF_TRUE || _obj == PDF_FALSE) {
  24. return Kind::Boolean;
  25. }
  26. if (_obj < PDF_LIMIT) {
  27. return Kind::Name;
  28. }
  29. switch (_obj->kind) {
  30. case PDF_INT: return Kind::Integer;
  31. case PDF_REAL: return Kind::Float;
  32. case PDF_STRING: return Kind::String;
  33. case PDF_NAME: return Kind::Name;
  34. case PDF_ARRAY: return Kind::Array;
  35. case PDF_DICT: return pdf_is_stream(_ctx, _obj) ? Kind::Stream : Kind::Dictionary;
  36. case PDF_INDIRECT: return Kind::Reference;
  37. }
  38. return Kind::Unknown;
  39. };
  40. PdfObject^ PdfObject::Wrap(pdf_obj* obj) {
  41. if (obj == PDF_NULL) {
  42. return (PdfObject^)PdfNull::Instance;
  43. }
  44. if (obj == PDF_TRUE) {
  45. return (PdfObject^)PdfBoolean::True;
  46. }
  47. if (obj == PDF_FALSE) {
  48. return (PdfObject^)PdfBoolean::False;
  49. }
  50. if (obj < PDF_LIMIT) {
  51. return gcnew PdfName(obj);
  52. }
  53. switch (obj->kind) {
  54. case PDF_INT: return gcnew PdfInteger(obj);
  55. case PDF_REAL: return gcnew PdfFloat(obj);
  56. case PDF_STRING: return gcnew PdfString(obj);
  57. case PDF_NAME: return gcnew PdfName(obj);
  58. case PDF_ARRAY: return gcnew PdfArray(obj);
  59. case PDF_DICT: return pdf_is_stream(Context::Ptr, obj) ? gcnew PdfStream(obj) : gcnew PdfDictionary(obj);
  60. case PDF_INDIRECT: return gcnew PdfReference(obj);
  61. }
  62. throw gcnew MuException("Invalid object kind: " + obj->kind.ToString());
  63. }
  64. bool PdfObject::Equals(PdfObject^ other) {
  65. return other && pdf_objcmp(_ctx, Ptr, other->Ptr) == 0;
  66. }
  67. pdf_obj* PdfContainer::NewPdfString(String^ text) {
  68. array<unsigned char>^ b;
  69. pin_ptr<unsigned char> pb;
  70. for each (auto ch in text) {
  71. if (ch > 127) {
  72. int l = (text->Length + 1) << 1;
  73. b = gcnew array<unsigned char>(l);
  74. b[0] = 0xFF;
  75. b[1] = 0xFE;
  76. pin_ptr<const wchar_t> ps = PtrToStringChars(text);
  77. pb = &b[2];
  78. memcpy(pb, ps, l - 2);
  79. goto MAKE_STRING;
  80. }
  81. }
  82. b = AsciiEncoding->GetBytes(text);
  83. MAKE_STRING:
  84. pb = &b[0];
  85. return pdf_new_string(Ctx, (const char*)(void*)pb, b->Length);
  86. }
  87. PdfObject^ PdfDictionary::Locate(...array<PdfNames>^ names) {
  88. auto ctx = Ctx;
  89. auto obj = Ptr;
  90. int length = names->Length;
  91. if (length == 0) {
  92. goto RETURN_NULL;
  93. }
  94. int i;
  95. for (i = 0; i < length - 1; i++) {
  96. obj = pdf_dict_get(ctx, obj, (pdf_obj*)names[i]);
  97. if (!obj) {
  98. goto RETURN_NULL;
  99. }
  100. obj = pdf_resolve_indirect_chain(ctx, obj);
  101. if (pdf_is_dict(ctx, obj) == false) {
  102. goto RETURN_NULL;
  103. }
  104. }
  105. return Wrap(pdf_resolve_indirect_chain(ctx, pdf_dict_get(ctx, obj, (pdf_obj*)names[i])));
  106. RETURN_NULL:
  107. return (PdfObject^)PdfNull::Instance;
  108. }
  109. array<Byte>^ PdfString::GetBytes() {
  110. size_t l;
  111. auto b = pdf_to_string(Ctx, Ptr, &l);
  112. array<Byte>^ r = gcnew array<Byte>(l);
  113. memcpy(&r, b, l);
  114. return r;
  115. }
  116. String^ PdfString::DecodePdfString() {
  117. size_t l;
  118. auto b = pdf_to_string(Ctx, Ptr, &l);
  119. if (b[0] == (char)254 && b[1] == (char)255) {
  120. return gcnew String(b, 2, l - 2, Encoding::BigEndianUnicode);
  121. }
  122. if (b[0] == (char)255 && b[1] == (char)254) {
  123. return gcnew String(b, 2, l - 2, Encoding::Unicode);
  124. }
  125. // PDFENCODE
  126. auto chars = new Char[l];
  127. for (size_t i = 0; i < l; i++) {
  128. chars[i] = fz_unicode_from_pdf_doc_encoding[b[i]];
  129. }
  130. return gcnew String(chars, 0, l);
  131. }
  132. String^ PdfString::Value::get() {
  133. return _string ? _string : (_string = DecodePdfString());
  134. }
  135. void PdfStream::SetBytes(array<Byte>^ data, bool isCompressed) {
  136. auto ctx = Ctx;
  137. pin_ptr<Byte> d = &data[0];
  138. fz_buffer* b = fz_new_buffer_from_copied_data(ctx, d, data->Length);
  139. pdf_update_stream(ctx, pdf_pin_document(ctx, Ptr), Ptr, b, isCompressed);
  140. fz_free(ctx, b);
  141. }