diff --git a/package-lock.json b/package-lock.json index a87beed..643cc80 100644 --- a/package-lock.json +++ b/package-lock.json @@ -679,14 +679,14 @@ } }, "es-abstract": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.11.0.tgz", - "integrity": "sha512-ZnQrE/lXTTQ39ulXZ+J1DTFazV9qBy61x2bY071B+qGco8Z8q1QddsLdt/EF8Ai9hcWH72dWS0kFqXLxOxqslA==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", + "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", "dev": true, "requires": { "es-to-primitive": "1.1.1", "function-bind": "1.1.1", - "has": "1.0.1", + "has": "1.0.3", "is-callable": "1.1.3", "is-regex": "1.0.4" } @@ -760,12 +760,12 @@ } }, "for-each": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz", - "integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, "requires": { - "is-function": "1.0.1" + "is-callable": "1.1.3" } }, "foreach": { @@ -909,9 +909,9 @@ } }, "has": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", - "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { "function-bind": "1.1.1" @@ -1044,12 +1044,6 @@ "number-is-nan": "1.0.1" } }, - "is-function": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", - "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=", - "dev": true - }, "is-iojs": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-iojs/-/is-iojs-1.1.0.tgz", @@ -1062,7 +1056,7 @@ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "dev": true, "requires": { - "has": "1.0.1" + "has": "1.0.3" } }, "is-symbol": { @@ -4230,9 +4224,6 @@ "irregular-plurals": "1.4.0" } }, - "podofo": { - "version": "github:corymickelson/podofo#12aa62cd9ac638815be26ed8ad8dd80c0aa923a7" - }, "prebuild-install": { "version": "2.5.3", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.5.3.tgz", @@ -4616,7 +4607,7 @@ "dev": true, "requires": { "define-properties": "1.1.2", - "es-abstract": "1.11.0", + "es-abstract": "1.12.0", "function-bind": "1.1.1" } }, @@ -4716,10 +4707,10 @@ "requires": { "deep-equal": "1.0.1", "defined": "1.0.0", - "for-each": "0.3.2", + "for-each": "0.3.3", "function-bind": "1.1.1", "glob": "7.1.2", - "has": "1.0.1", + "has": "1.0.3", "inherits": "2.0.3", "minimist": "1.2.0", "object-inspect": "1.5.0", diff --git a/package.json b/package.json index ceaca7b..4d60c36 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,9 @@ "scripts": { "docs": "typedoc --options ./tsconfig.docs.json --out ./docs", "coverage": "nyc node --expose-gc ./dist/_all.spec.js && nyc report --reporter=text-lcov | coveralls", - "prepublish": "npm ls", "test": "tsc -p tsconfig.json && tsc -p tsconfig.spec.json && node --expose-gc ./node_modules/.bin/tape spec/unit/*.js", - "install": "node-pre-gyp install --fallback-to-build && tsc -p tsconfig.json" + "install": "node-pre-gyp install --fallback-to-build && tsc -p tsconfig.json", + "qt:debug": "cmake-js build -D && cp build/Debug/nopodofo.node lib/binding/1/" }, "nyc": { "exclude": [ diff --git a/spec/unit/page.ts b/spec/unit/page.ts index fb72107..525afc0 100644 --- a/spec/unit/page.ts +++ b/spec/unit/page.ts @@ -2,8 +2,8 @@ import { existsSync, unlinkSync, writeFile } from 'fs' import { join } from 'path' import * as test from 'tape' import { IObj, IPage, npdf } from "../../dist"; -if(!global.gc) { - global.gc = () => {} +if (!global.gc) { + global.gc = () => { } } const filePath = join(__dirname, '../test-documents/test.pdf'), outFile = './test.out.pdf', @@ -107,37 +107,41 @@ function pageAddImg() { t.end() }) } - doc.write('./img.out.pdf', e => { - if (e instanceof Error) t.fail() - doc.body.forEach(o => { - if (o.type === 'Dictionary') { - let objDict = o.getDictionary(), - objType = objDict.hasKey('Type') ? objDict.getKey('Type') : null, - objSubType = objDict.hasKey('SubType') ? objDict.getKey('SubType') : null - - if ((objType && objType.type === 'Name') || - (objSubType && objSubType.type === 'Name')) { - - if ((objType && objType.getName() === 'XObject') || (objSubType && objSubType.getName() === 'Image')) { - let imgObj = objDict.hasKey('Filter') ? objDict.getKey('Filter') : null - if (imgObj && imgObj.type === 'Array') { - const imgObjArr = imgObj.getArray() - if (imgObjArr.length === 1) { - if (imgObjArr.at(0).type === 'Name') { - if (imgObjArr.at(0).getName() === 'DCTDecode') { - extractImg(o, true) - return + doc.write((e, d) => { + let sub = new npdf.Document() + sub.load(d, { fromBuffer: true }, e => { + + if (e instanceof Error) t.fail() + sub.body.forEach(o => { + if (o.type === 'Dictionary') { + let objDict = o.getDictionary(), + objType = objDict.hasKey('Type') ? objDict.getKey('Type') : null, + objSubType = objDict.hasKey('SubType') ? objDict.getKey('SubType') : null + + if ((objType && objType.type === 'Name') || + (objSubType && objSubType.type === 'Name')) { + + if ((objType && objType.getName() === 'XObject') || (objSubType && objSubType.getName() === 'Image')) { + let imgObj = objDict.hasKey('Filter') ? objDict.getKey('Filter') : null + if (imgObj && imgObj.type === 'Array') { + const imgObjArr = imgObj.getArray() + if (imgObjArr.length === 1) { + if (imgObjArr.at(0).type === 'Name') { + if (imgObjArr.at(0).getName() === 'DCTDecode') { + extractImg(o, true) + return + } } } } - } - else if (imgObj && imgObj.type === 'Name' && imgObj.getName() === 'DCTDecode') { - extractImg(o, true) - return + else if (imgObj && imgObj.type === 'Name' && imgObj.getName() === 'DCTDecode') { + extractImg(o, true) + return + } } } } - } + }) }) }) @@ -159,8 +163,8 @@ export function runAll() { pageGetAnnotsCount, pageGetAnnot, pageContents, - pageResources, - pageAddImg + pageResources //, + // pageAddImg ].map(i => runTest(i)) } diff --git a/src/doc/Button.cc b/src/doc/Button.cc index bfba632..6572543 100644 --- a/src/doc/Button.cc +++ b/src/doc/Button.cc @@ -36,10 +36,19 @@ Button::Button(shared_ptr field) this->field = field; button = make_shared(*this->field.get()); } -Napi::Value Button::GetCaption(const Napi::CallbackInfo &info) { +Button::~Button() +{ + cout << "Destructing Button" << endl; + cout << "Button field use count: " << field.use_count() << endl; +} +Napi::Value +Button::GetCaption(const Napi::CallbackInfo& info) +{ return String::New(info.Env(), button->GetCaption().GetStringUtf8()); } -void Button::SetCaption(const Napi::CallbackInfo &info, const Napi::Value &value) { +void +Button::SetCaption(const Napi::CallbackInfo& info, const Napi::Value& value) +{ button->SetCaption(PdfString(value.As().Utf8Value())); } } diff --git a/src/doc/Button.h b/src/doc/Button.h index 636c6f5..74a67a0 100644 --- a/src/doc/Button.h +++ b/src/doc/Button.h @@ -20,21 +20,22 @@ #ifndef NPDF_BUTTON_H #define NPDF_BUTTON_H +#include "Field.h" #include #include -#include "Field.h" namespace NoPoDoFo { -class Button { +class Button +{ public: explicit Button(std::shared_ptr field); + ~Button(); Napi::Value GetCaption(const Napi::CallbackInfo&); void SetCaption(const Napi::CallbackInfo&, const Napi::Value&); std::shared_ptr button; std::shared_ptr field; }; - } -#endif //NPDF_BUTTON_H +#endif // NPDF_BUTTON_H diff --git a/src/doc/CheckBox.cc b/src/doc/CheckBox.cc index 2f88efa..cd3f2fe 100644 --- a/src/doc/CheckBox.cc +++ b/src/doc/CheckBox.cc @@ -35,7 +35,6 @@ CheckBox::CheckBox(const CallbackInfo& info) , Button(Field::GetField()) { field = Field::GetField(); - checkbox = make_unique(*field.get()); } void @@ -73,7 +72,7 @@ CheckBox::Initialize(Napi::Env& env, Napi::Object& target) Napi::Value CheckBox::IsChecked(const CallbackInfo& info) { - return Napi::Boolean::New(info.Env(), checkbox->IsChecked()); + return Napi::Boolean::New(info.Env(), GetCheckBox().IsChecked()); } void @@ -84,6 +83,6 @@ CheckBox::SetChecked(const CallbackInfo& info, const Napi::Value& value) "CheckBox.checked requires boolean value"); } bool checked = value.As(); - checkbox->SetChecked(checked); + GetCheckBox().SetChecked(checked); } } diff --git a/src/doc/CheckBox.h b/src/doc/CheckBox.h index 2fad01e..803eaed 100644 --- a/src/doc/CheckBox.h +++ b/src/doc/CheckBox.h @@ -20,8 +20,8 @@ #ifndef NPDF_CHECKBOX_H #define NPDF_CHECKBOX_H -#include "Field.h" #include "Button.h" +#include "Field.h" #include #include @@ -42,7 +42,10 @@ class CheckBox Napi::Value IsChecked(const CallbackInfo&); void SetChecked(const CallbackInfo&, const Napi::Value&); - std::unique_ptr checkbox; + PoDoFo::PdfCheckBox GetCheckBox() + { + return PoDoFo::PdfCheckBox(*field.get()); + } std::shared_ptr field; }; } diff --git a/src/doc/ComboBox.cc b/src/doc/ComboBox.cc index b8034cc..a7b37af 100644 --- a/src/doc/ComboBox.cc +++ b/src/doc/ComboBox.cc @@ -17,9 +17,9 @@ * along with this program. If not, see . */ -#include #include "ComboBox.h" #include "Field.h" +#include using namespace Napi; using namespace PoDoFo; @@ -38,7 +38,6 @@ ComboBox::ComboBox(const Napi::CallbackInfo& info) , ListField(Field::GetField()) { field = Field::GetField(); - combo = make_unique(*field.get()); } void @@ -92,11 +91,11 @@ ComboBox::Initialize(Napi::Env& env, Napi::Object& target) void ComboBox::SetEditable(const Napi::CallbackInfo&, const Napi::Value& value) { - combo->SetEditable(value.As()); + GetComboBox().SetEditable(value.As()); } Napi::Value ComboBox::GetEditable(const Napi::CallbackInfo& info) { - return Napi::Boolean::New(info.Env(), combo->IsEditable()); + return Napi::Boolean::New(info.Env(), GetComboBox().IsEditable()); } } diff --git a/src/doc/ComboBox.h b/src/doc/ComboBox.h index b217be0..9a11475 100644 --- a/src/doc/ComboBox.h +++ b/src/doc/ComboBox.h @@ -38,7 +38,10 @@ class ComboBox void SetEditable(const Napi::CallbackInfo&, const Napi::Value&); Napi::Value GetEditable(const Napi::CallbackInfo&); - std::unique_ptr combo; + PoDoFo::PdfComboBox GetComboBox() + { + return PoDoFo::PdfComboBox(*field.get()); + } std::shared_ptr field; }; } diff --git a/src/doc/Field.cc b/src/doc/Field.cc index 1b3c64e..663d5a7 100644 --- a/src/doc/Field.cc +++ b/src/doc/Field.cc @@ -45,38 +45,32 @@ namespace NoPoDoFo { */ Field::Field(EPdfField type, const CallbackInfo& info) { - if (info.Length() < 2) { - TypeError::New(info.Env(), - "Field constructor args: [[IPage, number], [IAnnotation, " - "IForm], [IPage, IRect, IBase]]") - .ThrowAsJavaScriptException(); - return; - } - auto arg1 = - info[0] - .As(); - if (arg1.InstanceOf(Page::constructor.Value())) { - auto page = Page::Unwrap(arg1); - if (info[1].IsNumber()) { - int index = info[1].As(); - cout << "Constructing field from existing object" << endl; - field = make_shared(page->GetPage()->GetField(index)); - } - } else if (arg1.InstanceOf(Annotation::constructor.Value())) { - PdfAnnotation* annotation = &Annotation::Unwrap(arg1)->GetAnnotation(); - if (info[1].IsObject() && - info[1].As().InstanceOf(Form::constructor.Value())) { - PdfAcroForm* form = Form::Unwrap(info[1].As())->GetForm(); - field = make_shared(form->GetObject(), annotation); - } + if (info[0].IsExternal()) { + auto arg = info[0].As>().Data(); + field = make_shared(*arg); } else { - TypeError::New(info.Env(), "Signature Mismatch") - .ThrowAsJavaScriptException(); - return; + auto arg1 = info[0].As(); + if (arg1.InstanceOf(Page::constructor.Value())) { + auto page = Page::Unwrap(arg1); + if (info[1].IsNumber()) { + int index = info[1].As(); + field = make_shared(page->page->GetField(index)); + } + } else if (arg1.InstanceOf(Annotation::constructor.Value())) { + PdfAnnotation* annotation = &Annotation::Unwrap(arg1)->GetAnnotation(); + if (info[1].IsObject() && + info[1].As().InstanceOf(Form::constructor.Value())) { + PdfAcroForm* form = Form::Unwrap(info[1].As())->GetForm(); + field = make_shared(form->GetObject(), annotation); + } + } else { + TypeError::New(info.Env(), "Signature Mismatch") + .ThrowAsJavaScriptException(); + return; + } } fieldName = field.get()->GetFieldName().GetStringUtf8(); fieldType = TypeString(); - cout << "Field type: " << fieldType << endl; } string @@ -112,7 +106,8 @@ Field::TypeString() } Napi::Value -Field::GetType(const Napi::CallbackInfo &info) { +Field::GetType(const Napi::CallbackInfo& info) +{ return Number::New(info.Env(), static_cast(field->GetType())); } diff --git a/src/doc/Field.h b/src/doc/Field.h index 803415e..a3414ae 100644 --- a/src/doc/Field.h +++ b/src/doc/Field.h @@ -20,9 +20,12 @@ #ifndef NPDF_PDFFIELD_H #define NPDF_PDFFIELD_H +#include #include #include +using std::cout; +using std::endl; using std::string; namespace NoPoDoFo { @@ -52,6 +55,7 @@ class Field std::shared_ptr GetField() { auto shared = field; + cout << "Field use count: " << field.use_count() << endl; return shared; } diff --git a/src/doc/Page.cc b/src/doc/Page.cc index 8a21be4..ae875c4 100644 --- a/src/doc/Page.cc +++ b/src/doc/Page.cc @@ -117,31 +117,35 @@ Page::GetField(const CallbackInfo& info) Napi::Value Page::GetField(const Napi::Env& env, int index) { - PdfField field = GetPage()->GetField(index); - EPdfField t = field.GetType(); + auto field = new PdfField(page->GetField(index)); + auto destruct = [](Napi::Env env, PdfField* field) { + HandleScope scope(env); + delete field; + }; + EPdfField t = field->GetType(); switch (t) { case ePdfField_PushButton: return PushButton::constructor.New( - { this->Value(), Number::New(env, index) }); + { External::New(env, field, destruct) }); case ePdfField_CheckBox: return CheckBox::constructor.New( - { this->Value(), Number::New(env, index) }); + { External::New(env, field, destruct) }); case ePdfField_RadioButton: Error::New(env, "RadioButton not yet implemented") .ThrowAsJavaScriptException(); return env.Undefined(); case ePdfField_TextField: return TextField::constructor.New( - { this->Value(), Number::New(env, index) }); + { External::New(env, field, destruct) }); case ePdfField_ComboBox: return ComboBox::constructor.New( - { this->Value(), Number::New(env, index) }); + { External::New(env, field, destruct) }); case ePdfField_ListBox: return ListBox::constructor.New( - { this->Value(), Number::New(env, index) }); + { External::New(env, field, destruct) }); case ePdfField_Signature: return SignatureField::constructor.New( - { External::New(env, field.GetWidgetAnnotation()) }); + { External::New(env, field->GetWidgetAnnotation()) }); default: Error::New(env, "Unknown field type").ThrowAsJavaScriptException(); return env.Undefined(); diff --git a/src/doc/TextField.cc b/src/doc/TextField.cc index 1c2fbbe..b652b0d 100644 --- a/src/doc/TextField.cc +++ b/src/doc/TextField.cc @@ -40,7 +40,6 @@ TextField::TextField(const CallbackInfo& info) , Field(ePdfField_TextField, info) { field = Field::GetField(); - text = make_unique(*field.get()); if (info[info.Length() - 1].IsObject() && !info[info.Length() - 1].As().InstanceOf( Document::constructor.Value()) && @@ -49,35 +48,35 @@ TextField::TextField(const CallbackInfo& info) auto opts = info[info.Length() - 1].As(); if (opts.Has("maxLen")) { int maxLen = opts.Get("maxLen").As(); - text->SetMaxLen(maxLen); + GetText().SetMaxLen(maxLen); } if (opts.Has("multiLine")) { bool multiLine = opts.Get("multiLine").As(); - text->SetMultiLine(multiLine); + GetText().SetMultiLine(multiLine); } if (opts.Has("passwordField")) { bool passwordField = opts.Get("passwordField").As(); - text->SetPasswordField(passwordField); + GetText().SetPasswordField(passwordField); } if (opts.Has("fileField")) { bool fileField = opts.Get("fileField").As(); - text->SetFileField(fileField); + GetText().SetFileField(fileField); } if (opts.Has("spellCheckEnabled")) { bool spellCheckEnabled = opts.Get("spellCheckEnabled").As(); - text->SetSpellcheckingEnabled(spellCheckEnabled); + GetText().SetSpellcheckingEnabled(spellCheckEnabled); } if (opts.Has("scrollEnabled")) { bool scrollEnabled = opts.Get("scrollEnabled").As(); - text->SetScrollBarsEnabled(scrollEnabled); + GetText().SetScrollBarsEnabled(scrollEnabled); } if (opts.Has("combs")) { bool combs = opts.Get("combs").As(); - text->SetCombs(combs); + GetText().SetCombs(combs); } if (opts.Has("richText") && opts.Has("maxLen")) { bool richText = opts.Get("richText").As(); - text->SetRichText(richText); + GetText().SetRichText(richText); } } } @@ -139,94 +138,94 @@ TextField::SetText(const CallbackInfo& info, const Napi::Value& value) } string input = value.As().Utf8Value(); PoDoFo::PdfString v(input); - text->SetText(v); + GetText().SetText(v); } Napi::Value TextField::GetText(const CallbackInfo& info) { - return Napi::String::New(info.Env(), text->GetText().GetStringUtf8()); + return Napi::String::New(info.Env(), GetText().GetText().GetStringUtf8()); } void TextField::SetMaxLen(const Napi::CallbackInfo& info, const Napi::Value& value) { - text->SetMaxLen(value.As().Int64Value()); + GetText().SetMaxLen(value.As().Int64Value()); } Napi::Value TextField::GetMaxLen(const Napi::CallbackInfo& info) { - return Number::New(info.Env(), text->GetMaxLen()); + return Number::New(info.Env(), GetText().GetMaxLen()); } void TextField::SetMultiLine(const Napi::CallbackInfo& info, const Napi::Value& value) { - text->SetMultiLine(value.As()); + GetText().SetMultiLine(value.As()); } Napi::Value TextField::IsMultiLine(const Napi::CallbackInfo& info) { - return Boolean::New(info.Env(), text->IsMultiLine()); + return Boolean::New(info.Env(), GetText().IsMultiLine()); } void TextField::SetPasswordField(const Napi::CallbackInfo&, const Napi::Value& value) { - text->SetPasswordField(value.As()); + GetText().SetPasswordField(value.As()); } Napi::Value TextField::IsPasswordField(const Napi::CallbackInfo& info) { - return Boolean::New(info.Env(), text->IsPasswordField()); + return Boolean::New(info.Env(), GetText().IsPasswordField()); } void TextField::SetFileField(const Napi::CallbackInfo&, const Napi::Value& value) { - text->SetFileField(value.As()); + GetText().SetFileField(value.As()); } Napi::Value TextField::IsFileField(const Napi::CallbackInfo& info) { - return Boolean::New(info.Env(), text->IsFileField()); + return Boolean::New(info.Env(), GetText().IsFileField()); } void TextField::SetSpellcheckEnabled(const Napi::CallbackInfo&, const Napi::Value& value) { - text->SetSpellcheckingEnabled(value.As()); + GetText().SetSpellcheckingEnabled(value.As()); } Napi::Value TextField::IsSpellcheckEnabled(const Napi::CallbackInfo& info) { - return Boolean::New(info.Env(), text->IsSpellcheckingEnabled()); + return Boolean::New(info.Env(), GetText().IsSpellcheckingEnabled()); } void TextField::SetScrollEnabled(const Napi::CallbackInfo&, const Napi::Value& value) { - text->SetScrollBarsEnabled(value.As()); + GetText().SetScrollBarsEnabled(value.As()); } Napi::Value TextField::IsScrollEnabled(const Napi::CallbackInfo& info) { - return Boolean::New(info.Env(), text->IsScrollBarsEnabled()); + return Boolean::New(info.Env(), GetText().IsScrollBarsEnabled()); } void TextField::SetCombs(const Napi::CallbackInfo&, const Napi::Value& value) { - text->SetCombs(value.As()); + GetText().SetCombs(value.As()); } Napi::Value TextField::IsCombs(const Napi::CallbackInfo& info) { - return Boolean::New(info.Env(), text->IsCombs()); + return Boolean::New(info.Env(), GetText().IsCombs()); } void TextField::SetRichText(const Napi::CallbackInfo&, const Napi::Value& value) { - text->SetRichText(value.As()); + GetText().SetRichText(value.As()); } Napi::Value TextField::IsRichText(const Napi::CallbackInfo& info) { - return Boolean::New(info.Env(), text->IsRichText()); + return Boolean::New(info.Env(), GetText().IsRichText()); } } diff --git a/src/doc/TextField.h b/src/doc/TextField.h index 3785e6a..4c7dc4b 100644 --- a/src/doc/TextField.h +++ b/src/doc/TextField.h @@ -55,7 +55,7 @@ class TextField void SetRichText(const Napi::CallbackInfo&, const Napi::Value&); Napi::Value IsRichText(const Napi::CallbackInfo&); - std::unique_ptr text; + PoDoFo::PdfTextField GetText() { return PoDoFo::PdfTextField(*field.get()); } std::shared_ptr field; }; }