diff --git a/DesktopEditor/doctrenderer/docbuilder_p.cpp b/DesktopEditor/doctrenderer/docbuilder_p.cpp index 038da31197..6abc4f0684 100644 --- a/DesktopEditor/doctrenderer/docbuilder_p.cpp +++ b/DesktopEditor/doctrenderer/docbuilder_p.cpp @@ -492,12 +492,12 @@ namespace NSDoctRenderer if (oParent->isArray()) { JSSmart oParentArray = oParent->toArray(); - oParentArray->set(m_internal->m_parent->m_parent_index, m_internal->m_value.GetPointer()); + oParentArray->set(m_internal->m_parent->m_parent_index, m_internal->m_value); } else if (oParent->isObject() && !m_internal->m_parent->m_parent_prop_name.empty()) { JSSmart oParentObject = oParent->toObject(); - oParentObject->set(m_internal->m_parent->m_parent_prop_name.c_str(), m_internal->m_value.GetPointer()); + oParentObject->set(m_internal->m_parent->m_parent_prop_name.c_str(), m_internal->m_value); } } @@ -729,7 +729,7 @@ namespace NSDoctRenderer std::string sPropA = U_TO_UTF8(sProp); value.m_internal->CheckNative(); - m_internal->m_value->toObject()->set(sPropA.c_str(), value.m_internal->m_value.GetPointer()); + m_internal->m_value->toObject()->set(sPropA.c_str(), value.m_internal->m_value); } void CDocBuilderValue::SetProperty(const wchar_t* name, CDocBuilderValue value) { @@ -742,7 +742,7 @@ namespace NSDoctRenderer JSSmart array = m_internal->m_value->toArray(); value.m_internal->CheckNative(); - array->set(index, value.m_internal->m_value.GetPointer()); + array->set(index, value.m_internal->m_value); } // primitives diff --git a/DesktopEditor/doctrenderer/doctrenderer.pro b/DesktopEditor/doctrenderer/doctrenderer.pro index 17a3ff8cff..10ab29b02d 100644 --- a/DesktopEditor/doctrenderer/doctrenderer.pro +++ b/DesktopEditor/doctrenderer/doctrenderer.pro @@ -21,62 +21,73 @@ ADD_DEPENDENCY(graphics, kernel, UnicodeConverter, kernel_network) core_android:DEFINES += DISABLE_MEMORY_LIMITATION HEADERS += \ - config.h \ - doctrenderer.h \ - docbuilder.h + config.h \ + doctrenderer.h \ + docbuilder.h SOURCES += \ - nativecontrol.cpp \ - doctrenderer.cpp \ - docbuilder.cpp \ - docbuilder_p.cpp \ - graphics.cpp \ + nativecontrol.cpp \ + doctrenderer.cpp \ + docbuilder.cpp \ + docbuilder_p.cpp \ + graphics.cpp \ hash.cpp SOURCES += \ - ../../Common/OfficeFileFormatChecker2.cpp \ - ../../Common/3dParty/pole/pole.cpp \ - ../../OOXML/Base/unicode_util.cpp + ../../Common/OfficeFileFormatChecker2.cpp \ + ../../Common/3dParty/pole/pole.cpp \ + ../../OOXML/Base/unicode_util.cpp HEADERS += \ - docbuilder_p.h \ - nativecontrol.h \ - graphics.h \ - hash.h + docbuilder_p.h \ + nativecontrol.h \ + graphics.h \ + hash.h HEADERS += \ - embed/PointerEmbed.h \ - embed/ZipEmbed.h \ - embed/GraphicsEmbed.h \ - embed/MemoryStreamEmbed.h \ - embed/NativeControlEmbed.h \ - embed/NativeBuilderEmbed.h \ - embed/NativeBuilderDocumentEmbed.h \ - embed/TextMeasurerEmbed.h \ - embed/HashEmbed.h \ - embed/Default.h \ - js_internal/js_base.h + embed/PointerEmbed.h \ + embed/ZipEmbed.h \ + embed/GraphicsEmbed.h \ + embed/MemoryStreamEmbed.h \ + embed/NativeControlEmbed.h \ + embed/NativeBuilderEmbed.h \ + embed/NativeBuilderDocumentEmbed.h \ + embed/TextMeasurerEmbed.h \ + embed/HashEmbed.h \ + embed/Default.h \ + js_internal/js_base.h SOURCES += \ - embed/PointerEmbed.cpp \ - embed/ZipEmbed.cpp \ - embed/GraphicsEmbed.cpp \ - embed/MemoryStreamEmbed.cpp \ - embed/NativeControlEmbed.cpp \ - embed/NativeBuilderEmbed.cpp \ - embed/NativeBuilderDocumentEmbed.cpp \ - embed/TextMeasurerEmbed.cpp \ - embed/HashEmbed.cpp \ - embed/Default.cpp + embed/PointerEmbed.cpp \ + embed/ZipEmbed.cpp \ + embed/GraphicsEmbed.cpp \ + embed/MemoryStreamEmbed.cpp \ + embed/NativeControlEmbed.cpp \ + embed/NativeBuilderEmbed.cpp \ + embed/NativeBuilderDocumentEmbed.cpp \ + embed/TextMeasurerEmbed.cpp \ + embed/HashEmbed.cpp \ + embed/Default.cpp + +# Serialize objects to JS +HEADERS += \ + json/json.h \ + json/json_p.h \ + json/json_values.h \ + json/serialization.h + +SOURCES += \ + json/json.cpp \ + json/json_values.cpp include($$PWD/js_internal/js_base.pri) !use_javascript_core { - build_xp:DESTDIR=$$DESTDIR/xp + build_xp:DESTDIR=$$DESTDIR/xp } use_javascript_core { - OBJECTIVE_SOURCES += ../common/Mac/NSString+StringUtils.mm + OBJECTIVE_SOURCES += ../common/Mac/NSString+StringUtils.mm } # files for embedded classes diff --git a/DesktopEditor/doctrenderer/js_internal/js_base.cpp b/DesktopEditor/doctrenderer/js_internal/js_base.cpp index 4f275ae2d2..7df327b703 100644 --- a/DesktopEditor/doctrenderer/js_internal/js_base.cpp +++ b/DesktopEditor/doctrenderer/js_internal/js_base.cpp @@ -65,14 +65,9 @@ namespace NSJSBase { { } - void CJSObject::set(const char* name, JSSmart value) - { - this->set(name, value.GetPointer()); - } void CJSObject::set(const char* name, JSSmart obj) { - JSSmart value = obj->toValue(); - this->set(name, value.GetPointer()); + this->set(name, obj->toValue()); } CJSArray::CJSArray() diff --git a/DesktopEditor/doctrenderer/js_internal/js_base.h b/DesktopEditor/doctrenderer/js_internal/js_base.h index 319308308d..e7d9184e85 100644 --- a/DesktopEditor/doctrenderer/js_internal/js_base.h +++ b/DesktopEditor/doctrenderer/js_internal/js_base.h @@ -215,19 +215,22 @@ namespace NSJSBase * Returns specified property of the object. * @param name The name of a property. */ - virtual JSSmart get(const char* name) = 0; + virtual JSSmart get(const char* name) = 0; /** * Sets a property of the object. * @param name The name of a property. * @param value The value of a property. */ - virtual void set(const char* name, CJSValue* value) = 0; + virtual void set(const char* name, JSSmart value) = 0; virtual void set(const char* name, const int& value) = 0; virtual void set(const char* name, const double& value) = 0; - // Common funcs - void set(const char* name, JSSmart value); + // Common function void set(const char* name, JSSmart value); + /** + * Returns a vector containing the names of the properties of this object as strings, including properties from prototype objects. + */ + virtual std::vector getPropertyNames() = 0; /** * Returns a pointer to the native embedded object. */ @@ -269,8 +272,7 @@ namespace NSJSBase * @param index The index of the array value. * @param value The array value to be set. */ - virtual void set(const int& index, CJSValue* value) = 0; - virtual void set(const int& index, const bool& value) = 0; + virtual void set(const int& index, JSSmart value) = 0; virtual void set(const int& index, const int& value) = 0; virtual void set(const int& index, const double& value) = 0; @@ -278,7 +280,7 @@ namespace NSJSBase * Add the specified value to the array. * @param value The value to be added. */ - virtual void add(CJSValue* value) = 0; + virtual void add(JSSmart value) = 0; /** * Add null to the array. */ @@ -673,7 +675,7 @@ namespace NSJSBase * * NOTE: If you don't want to export certain functions from your embedded class for some reason, * then add the inline comment "[noexport]" at the start of a function declaration. - * Also you can use `#ifdef ... #endif` blocks (see doctrenderer/test/internal/Embed.h for an example). + * Also you can use `#ifdef ... #endif` blocks (see doctrenderer/test/embed/external/Embed.h for an example). */ #endif // _CORE_EXT_JS_BASE_H_ diff --git a/DesktopEditor/doctrenderer/js_internal/jsc/jsc_base.h b/DesktopEditor/doctrenderer/js_internal/jsc/jsc_base.h index 1a82a4e0b1..e71d0a10d6 100644 --- a/DesktopEditor/doctrenderer/js_internal/jsc/jsc_base.h +++ b/DesktopEditor/doctrenderer/js_internal/jsc/jsc_base.h @@ -12,25 +12,25 @@ namespace NSJSBase { - class CJSContextPrivate - { - public: - JSContext* context; - std::vector m_arThreads; + class CJSContextPrivate + { + public: + JSContext* context; + std::vector m_arThreads; - public: - CJSContextPrivate() - { - context = nil; - } - ~CJSContextPrivate() - { - context = nil; - } + public: + CJSContextPrivate() + { + context = nil; + } + ~CJSContextPrivate() + { + context = nil; + } - static JSContext* GetCurrentContext(); - static bool IsOldVersion(); - }; + static JSContext* GetCurrentContext(); + static bool IsOldVersion(); + }; // embed id CreateEmbedNativeObject(NSString* name); @@ -38,495 +38,501 @@ namespace NSJSBase namespace NSJSBase { - template - class CJSValueJSCTemplate : public T - { - public: - JSValue* value; + template + class CJSValueJSCTemplate : public T + { + public: + JSValue* value; - CJSValueJSCTemplate() - { - value = nil; - } - CJSValueJSCTemplate(JSValue* _value) - { - value = _value; - } + CJSValueJSCTemplate() + { + value = nil; + } + CJSValueJSCTemplate(JSValue* _value) + { + value = _value; + } - public: + public: + virtual ~CJSValueJSCTemplate() + { + value = nil; + } - virtual ~CJSValueJSCTemplate() - { - value = nil; - } + virtual bool isUndefined(); + virtual bool isNull(); + virtual bool isBool(); + virtual bool isNumber(); + virtual bool isString(); + virtual bool isArray(); + virtual bool isTypedArray(); + virtual bool isObject(); + virtual bool isFunction(); + virtual bool isEmpty(); - virtual bool isUndefined(); - virtual bool isNull(); - virtual bool isBool(); - virtual bool isNumber(); - virtual bool isString(); - virtual bool isArray(); - virtual bool isTypedArray(); - virtual bool isObject(); - virtual bool isFunction(); - virtual bool isEmpty(); - - virtual void doUndefined(); - virtual void doNull(); - virtual bool toBool(); - virtual int toInt32(); - virtual unsigned int toUInt32(); - virtual double toDouble(); - virtual std::string toStringA(); - virtual std::wstring toStringW(); + virtual void doUndefined(); + virtual void doNull(); + virtual bool toBool(); + virtual int toInt32(); + virtual unsigned int toUInt32(); + virtual double toDouble(); + virtual std::string toStringA(); + virtual std::wstring toStringW(); virtual JSSmart toObject(); virtual JSSmart toArray(); virtual JSSmart toTypedArray(); virtual JSSmart toFunction(); - JSContext* getContext() - { - if (nil == value || nil == value.context) - return CJSContextPrivate::GetCurrentContext(); - return value.context; - } - }; + JSContext* getContext() + { + if (nil == value || nil == value.context) + return CJSContextPrivate::GetCurrentContext(); + return value.context; + } + }; - typedef CJSValueJSCTemplate CJSValueJSC; + typedef CJSValueJSCTemplate CJSValueJSC; - class CJSObjectJSC : public CJSValueJSCTemplate - { - public: - CJSObjectJSC() - { - } - CJSObjectJSC(JSValue* _value) : CJSValueJSCTemplate(_value) - { - } + class CJSObjectJSC : public CJSValueJSCTemplate + { + public: + CJSObjectJSC() + { + } + CJSObjectJSC(JSValue* _value) : CJSValueJSCTemplate(_value) + { + } - virtual ~CJSObjectJSC() - { - value = nil; - } + virtual ~CJSObjectJSC() + { + value = nil; + } virtual JSSmart get(const char* name) - { - CJSValueJSC* _value = new CJSValueJSC(); - _value->value = [value valueForProperty:[[NSString alloc] initWithUTF8String:name]]; - return _value; - } + { + CJSValueJSC* _value = new CJSValueJSC(); + _value->value = [value valueForProperty:[[NSString alloc] initWithUTF8String:name]]; + return _value; + } - virtual void set(const char* name, CJSValue* value_param) - { - CJSValueJSC* _value = static_cast(value_param); - [value setValue:_value->value forProperty:[[NSString alloc] initWithUTF8String:name]]; - } + virtual void set(const char* name, JSSmart value_param) + { + CJSValueJSC* _value = static_cast(value_param.GetPointer()); + [value setValue:_value->value forProperty:[[NSString alloc] initWithUTF8String:name]]; + } - virtual void set(const char* name, const int& _value) - { - [value setValue:[JSValue valueWithInt32:_value inContext: getContext()] forProperty:[[NSString alloc] initWithUTF8String:name]]; - } + virtual void set(const char* name, const int& _value) + { + [value setValue:[JSValue valueWithInt32:_value inContext:getContext()] forProperty:[[NSString alloc] initWithUTF8String:name]]; + } - virtual void set(const char* name, const double& _value) - { - [value setValue:[JSValue valueWithDouble:_value inContext: getContext()] forProperty:[[NSString alloc] initWithUTF8String:name]]; - } + virtual void set(const char* name, const double& _value) + { + [value setValue:[JSValue valueWithDouble:_value inContext:getContext()] forProperty:[[NSString alloc] initWithUTF8String:name]]; + } - virtual CJSEmbedObject* getNative() - { - id _wrapper = [value toObject]; - if ([_wrapper conformsToProtocol:@protocol(JSEmbedObjectProtocol)]) - { - return (CJSEmbedObject*)([_wrapper getNative]); - } - return NULL; - } + virtual std::vector getPropertyNames() + { + NSArray* names = [[value toObject] allKeys]; + uint32_t len = [names count]; - virtual JSSmart call_func(const char* name, const int argc = 0, JSSmart argv[] = NULL) - { - NSMutableArray* arr = nil; + std::vector ret(len); + for (uint32_t i = 0; i < len; i++) + { + NSString* name = [names objectAtIndex:i]; + ret[i] = [name stdstring]; + } - if (argc > 0) - { - arr = [[NSMutableArray alloc] init]; - for (int i = 0; i < argc; ++i) - { - CJSValueJSC* _val = (CJSValueJSC*)argv[i].operator ->(); - [arr addObject:_val->value]; - } - } + return ret; + } - CJSValueJSC* _return = new CJSValueJSC(); - _return->value = [value invokeMethod: [[NSString alloc] initWithUTF8String:name] - withArguments: arr]; + virtual CJSEmbedObject* getNative() + { + id _wrapper = [value toObject]; + if ([_wrapper conformsToProtocol:@protocol(JSEmbedObjectProtocol)]) + { + return (CJSEmbedObject*)([_wrapper getNative]); + } + return NULL; + } - return _return; - } + virtual JSSmart call_func(const char* name, const int argc = 0, JSSmart argv[] = NULL) + { + NSMutableArray* arr = nil; - virtual JSSmart toValue() - { - CJSValueJSC* _value = new CJSValueJSC(); - _value->value = value; - //_value->value = [JSValue valueWithJSValueRef:[value JSValueRef] inContext:context]; - return _value; - } - }; + if (argc > 0) + { + arr = [[NSMutableArray alloc] init]; + for (int i = 0; i < argc; ++i) + { + CJSValueJSC* _val = (CJSValueJSC*)argv[i].operator->(); + [arr addObject:_val->value]; + } + } - class CJSArrayJSC : public CJSValueJSCTemplate - { - public: - int m_count; - public: - CJSArrayJSC() - { - m_count = 0; - } - virtual ~CJSArrayJSC() - { - value = nil; - } + CJSValueJSC* _return = new CJSValueJSC(); + _return->value = [value invokeMethod:[[NSString alloc] initWithUTF8String:name] withArguments:arr]; - virtual int getCount() - { - int nCount = 0; - JSValue* _ret = [value valueForProperty:@"length"]; - if (nil != _ret && NO == [_ret isUndefined]) - nCount = [_ret toInt32]; - _ret = nil; - return nCount; - } + return _return; + } - virtual JSSmart get(const int& index) - { - CJSValueJSC* _value = new CJSValueJSC(); - _value->value = [value valueAtIndex:(NSUInteger)index]; - return _value; - } + virtual JSSmart toValue() + { + CJSValueJSC* _value = new CJSValueJSC(); + _value->value = value; + //_value->value = [JSValue valueWithJSValueRef:[value JSValueRef] inContext:context]; + return _value; + } + }; - virtual void set(const int& index, CJSValue* value_param) - { - CJSValueJSC* _value = static_cast(value_param); - [value setValue:_value->value atIndex:index]; - } + class CJSArrayJSC : public CJSValueJSCTemplate + { + public: + int m_count; - virtual void add(CJSValue* value_param) - { - set(getCount(), value_param); - } + public: + CJSArrayJSC() + { + m_count = 0; + } + virtual ~CJSArrayJSC() + { + value = nil; + } - virtual void set(const int& index, const bool& _value) - { - [value setValue:[JSValue valueWithBool:_value inContext : getContext()] atIndex:index]; - } + virtual int getCount() + { + int nCount = 0; + JSValue* _ret = [value valueForProperty:@"length"]; + if (nil != _ret && NO == [_ret isUndefined]) + nCount = [_ret toInt32]; + _ret = nil; + return nCount; + } - virtual void set(const int& index, const int& _value) - { - [value setValue:[JSValue valueWithInt32:_value inContext : getContext()] atIndex:index]; - } + virtual JSSmart get(const int& index) + { + CJSValueJSC* _value = new CJSValueJSC(); + _value->value = [value valueAtIndex:(NSUInteger)index]; + return _value; + } - virtual void set(const int& index, const double& _value) - { - [value setValue:[JSValue valueWithDouble:_value inContext : getContext()] atIndex:index]; - } + virtual void set(const int& index, JSSmart value_param) + { + CJSValueJSC* _value = static_cast(value_param.GetPointer()); + [value setValue:_value->value atIndex:index]; + } - virtual void add_null() - { - [value setValue:[JSValue valueWithNullInContext:getContext()] atIndex:m_count++]; - } + virtual void add(JSSmart value_param) + { + set(getCount(), value_param); + } - virtual void add_undefined() - { - [value setValue:nil atIndex:m_count++]; - } + virtual void set(const int& index, const int& _value) + { + [value setValue:[JSValue valueWithInt32:_value inContext:getContext()] atIndex:index]; + } - virtual void add_bool(const bool& _value) - { - [value setValue:[JSValue valueWithBool:_value inContext : getContext()] atIndex:m_count++]; - } + virtual void set(const int& index, const double& _value) + { + [value setValue:[JSValue valueWithDouble:_value inContext:getContext()] atIndex:index]; + } - virtual void add_byte(const BYTE& _value) - { - [value setValue:[JSValue valueWithInt32:(int)_value inContext : getContext()] atIndex:m_count++]; - } + virtual void add_null() + { + [value setValue:[JSValue valueWithNullInContext:getContext()] atIndex:m_count++]; + } - virtual void add_int(const int& _value) - { - [value setValue:[JSValue valueWithInt32:_value inContext : getContext()] atIndex:m_count++]; - } + virtual void add_undefined() + { + [value setValue:nil atIndex:m_count++]; + } - virtual void add_double(const double& _value) - { - [value setValue:[JSValue valueWithDouble:_value inContext : getContext()] atIndex:m_count++]; - } + virtual void add_bool(const bool& _value) + { + [value setValue:[JSValue valueWithBool:_value inContext:getContext()] atIndex:m_count++]; + } - virtual void add_stringa(const std::string& _value) - { - [value setValue:[NSString stringWithAString:_value] atIndex:m_count++]; - } + virtual void add_byte(const BYTE& _value) + { + [value setValue:[JSValue valueWithInt32:(int)_value inContext:getContext()] atIndex:m_count++]; + } - virtual void add_string(const std::wstring& _value) - { - [value setValue:[NSString stringWithWString:_value] atIndex:m_count++]; - } + virtual void add_int(const int& _value) + { + [value setValue:[JSValue valueWithInt32:_value inContext:getContext()] atIndex:m_count++]; + } - virtual JSSmart toValue() - { - CJSValueJSC* _value = new CJSValueJSC(); - _value->value = value; - return _value; - } - }; + virtual void add_double(const double& _value) + { + [value setValue:[JSValue valueWithDouble:_value inContext:getContext()] atIndex:m_count++]; + } - class CJSTypedArrayJSC : public CJSValueJSCTemplate - { - public: - CJSTypedArrayJSC(JSContext* _context, BYTE* data = NULL, int count = 0, const bool& isExternalize = true) - { - if (0 >= count) - return; + virtual void add_stringa(const std::string& _value) + { + [value setValue:[NSString stringWithAString:_value] atIndex:m_count++]; + } - if (!CJSContextPrivate::IsOldVersion()) - { - JSObjectRef object = JSObjectMakeTypedArrayWithBytesNoCopy(_context.JSGlobalContextRef, - kJSTypedArrayTypeUint8Array, - (void*)data, (size_t)count, - isExternalize ? data_no_destroy_memory : data_destroy_memory, - nullptr, nullptr); - if (object) - { - value = [JSValue valueWithJSValueRef:object inContext:_context]; - } - } - else - { - char* pDst = NULL; - int nDstLen = 0; - NSFile::CBase64Converter::Encode(data, count, pDst, nDstLen, NSBase64::B64_BASE64_FLAG_NOCRLF); + virtual void add_string(const std::wstring& _value) + { + [value setValue:[NSString stringWithWString:_value] atIndex:m_count++]; + } - std::string sCode = "jsc_fromBase64(\"" + std::string(pDst, nDstLen) + "\", " + std::to_string(count) + ");"; - RELEASEARRAYOBJECTS(pDst); - value = [_context evaluateScript:[NSString stringWithAString:sCode]]; - } - } - virtual ~CJSTypedArrayJSC() - { - value = nil; - } + virtual JSSmart toValue() + { + CJSValueJSC* _value = new CJSValueJSC(); + _value->value = value; + return _value; + } + }; - static void data_destroy_memory(void* bytes, void* deallocatorContext) - { - NSJSBase::NSAllocator::Free((unsigned char*)bytes, 0); - } - static void data_no_destroy_memory(void* bytes, void* deallocatorContext) - { - } + class CJSTypedArrayJSC : public CJSValueJSCTemplate + { + public: + CJSTypedArrayJSC(JSContext* _context, BYTE* data = NULL, int count = 0, const bool& isExternalize = true) + { + if (0 >= count) + return; - virtual int getCount() - { - if (nil == value) - return 0; - JSContext* context = getContext(); - if (!CJSContextPrivate::IsOldVersion()) - { - JSObjectRef obj = JSValueToObject(context.JSGlobalContextRef, value.JSValueRef, NULL); - return (int)JSObjectGetTypedArrayByteLength(context.JSGlobalContextRef, obj, NULL); - } - int nCount = 0; - JSValue* _ret = [value valueForProperty:@"length"]; - if (nil != _ret && NO == [_ret isUndefined]) - nCount = [_ret toInt32]; - _ret = nil; - return nCount; - } + if (!CJSContextPrivate::IsOldVersion()) + { + JSObjectRef object = JSObjectMakeTypedArrayWithBytesNoCopy( + _context.JSGlobalContextRef, kJSTypedArrayTypeUint8Array, (void*)data, (size_t)count, isExternalize ? data_no_destroy_memory : data_destroy_memory, nullptr, nullptr); + if (object) + { + value = [JSValue valueWithJSValueRef:object inContext:_context]; + } + } + else + { + char* pDst = NULL; + int nDstLen = 0; + NSFile::CBase64Converter::Encode(data, count, pDst, nDstLen, NSBase64::B64_BASE64_FLAG_NOCRLF); - virtual CJSDataBuffer getData() - { - JSContext* context = getContext(); - CJSDataBuffer buffer; - if (!CJSContextPrivate::IsOldVersion()) - { - JSObjectRef obj = JSValueToObject(context.JSGlobalContextRef, value.JSValueRef, NULL); - buffer.IsExternalize = false; - buffer.Data = (BYTE*)JSObjectGetTypedArrayBytesPtr(context.JSGlobalContextRef, obj, NULL); - buffer.Len = (size_t)JSObjectGetTypedArrayByteLength(context.JSGlobalContextRef, obj, NULL); - return buffer; - } + std::string sCode = "jsc_fromBase64(\"" + std::string(pDst, nDstLen) + "\", " + std::to_string(count) + ");"; + RELEASEARRAYOBJECTS(pDst); + value = [_context evaluateScript:[NSString stringWithAString:sCode]]; + } + } + virtual ~CJSTypedArrayJSC() + { + value = nil; + } - NSMutableArray* arr = [[NSMutableArray alloc] init]; - [arr addObject:value]; + static void data_destroy_memory(void* bytes, void* deallocatorContext) + { + NSJSBase::NSAllocator::Free((unsigned char*)bytes, 0); + } + static void data_no_destroy_memory(void* bytes, void* deallocatorContext) + { + } - JSValue* dataBase64 = [context[@"jsc_toBase64"] callWithArguments:arr]; - std::string sBase64Data = [[dataBase64 toString] stdstring]; - dataBase64 = nil; + virtual int getCount() + { + if (nil == value) + return 0; + JSContext* context = getContext(); + if (!CJSContextPrivate::IsOldVersion()) + { + JSObjectRef obj = JSValueToObject(context.JSGlobalContextRef, value.JSValueRef, NULL); + return (int)JSObjectGetTypedArrayByteLength(context.JSGlobalContextRef, obj, NULL); + } + int nCount = 0; + JSValue* _ret = [value valueForProperty:@"length"]; + if (nil != _ret && NO == [_ret isUndefined]) + nCount = [_ret toInt32]; + _ret = nil; + return nCount; + } - buffer.IsExternalize = true; + virtual CJSDataBuffer getData() + { + JSContext* context = getContext(); + CJSDataBuffer buffer; + if (!CJSContextPrivate::IsOldVersion()) + { + JSObjectRef obj = JSValueToObject(context.JSGlobalContextRef, value.JSValueRef, NULL); + buffer.IsExternalize = false; + buffer.Data = (BYTE*)JSObjectGetTypedArrayBytesPtr(context.JSGlobalContextRef, obj, NULL); + buffer.Len = (size_t)JSObjectGetTypedArrayByteLength(context.JSGlobalContextRef, obj, NULL); + return buffer; + } - int nLenDst = NSBase64::Base64DecodeGetRequiredLength((int)sBase64Data.length()); - buffer.Data = NSAllocator::Alloc(nLenDst); + NSMutableArray* arr = [[NSMutableArray alloc] init]; + [arr addObject:value]; - if (FALSE == NSBase64::Base64Decode(sBase64Data.c_str(), (int)sBase64Data.length(), buffer.Data, &nLenDst)) - { - buffer.Free(); - return buffer; - } - return buffer; - } + JSValue* dataBase64 = [context[@"jsc_toBase64"] callWithArguments:arr]; + std::string sBase64Data = [[dataBase64 toString] stdstring]; + dataBase64 = nil; - virtual JSSmart toValue() - { - CJSValueJSC* _value = new CJSValueJSC(); - _value->value = value; - return _value; - } - }; + buffer.IsExternalize = true; - class CJSFunctionJSC : public CJSValueJSCTemplate - { - public: - CJSFunctionJSC() - { - } - virtual ~CJSFunctionJSC() - { - value = nil; - } + int nLenDst = NSBase64::Base64DecodeGetRequiredLength((int)sBase64Data.length()); + buffer.Data = NSAllocator::Alloc(nLenDst); + + if (FALSE == NSBase64::Base64Decode(sBase64Data.c_str(), (int)sBase64Data.length(), buffer.Data, &nLenDst)) + { + buffer.Free(); + return buffer; + } + return buffer; + } + + virtual JSSmart toValue() + { + CJSValueJSC* _value = new CJSValueJSC(); + _value->value = value; + return _value; + } + }; + + class CJSFunctionJSC : public CJSValueJSCTemplate + { + public: + CJSFunctionJSC() + { + } + virtual ~CJSFunctionJSC() + { + value = nil; + } virtual JSSmart Call(CJSValue* recv, int argc, JSSmart argv[]) - { - NSMutableArray* arr = [[NSMutableArray alloc] init]; - for (int i = 0; i < argc; ++i) - { - CJSValueJSC* _val = (CJSValueJSC*)argv[i].operator ->(); - [arr addObject:_val->value]; - } + { + NSMutableArray* arr = [[NSMutableArray alloc] init]; + for (int i = 0; i < argc; ++i) + { + CJSValueJSC* _val = (CJSValueJSC*)argv[i].operator->(); + [arr addObject:_val->value]; + } - CJSValueJSC* _return = new CJSValueJSC(); - _return->value = [value callWithArguments:arr]; + CJSValueJSC* _return = new CJSValueJSC(); + _return->value = [value callWithArguments:arr]; - return _return; - } - }; + return _return; + } + }; - template + template JSSmart CJSValueJSCTemplate::toObject() - { - CJSObjectJSC* _value = new CJSObjectJSC(); - _value->value = value; - return _value; - } + { + CJSObjectJSC* _value = new CJSObjectJSC(); + _value->value = value; + return _value; + } - template + template JSSmart CJSValueJSCTemplate::toArray() - { - CJSArrayJSC* _value = new CJSArrayJSC(); - _value->value = value; - return _value; - } + { + CJSArrayJSC* _value = new CJSArrayJSC(); + _value->value = value; + return _value; + } - template + template JSSmart CJSValueJSCTemplate::toTypedArray() - { - CJSTypedArrayJSC* _value = new CJSTypedArrayJSC(getContext()); - _value->value = value; - return _value; - } + { + CJSTypedArrayJSC* _value = new CJSTypedArrayJSC(getContext()); + _value->value = value; + return _value; + } - template + template JSSmart CJSValueJSCTemplate::toFunction() - { - CJSFunctionJSC* _value = new CJSFunctionJSC(); - _value->value = value; - return _value; - } -} + { + CJSFunctionJSC* _value = new CJSFunctionJSC(); + _value->value = value; + return _value; + } +} // namespace NSJSBase namespace NSJSBase { - // TRY - CATCH - class CJSCTryCatch : public CJSTryCatch - { - public: - JSContext* context; + // TRY - CATCH + class CJSCTryCatch : public CJSTryCatch + { + public: + JSContext* context; - public: - CJSCTryCatch() : CJSTryCatch() - { - context = CJSContextPrivate::GetCurrentContext(); - } - virtual ~CJSCTryCatch() - { - context = nil; - } + public: + CJSCTryCatch() : CJSTryCatch() + { + context = CJSContextPrivate::GetCurrentContext(); + } + virtual ~CJSCTryCatch() + { + context = nil; + } - public: - virtual bool Check(); - }; + public: + virtual bool Check(); + }; } inline JSSmart js_value(JSValue* _value) { - return new NSJSBase::CJSValueJSC(_value); + return new NSJSBase::CJSValueJSC(_value); } inline JSSmart js_object(JSValue* _value) { - return new NSJSBase::CJSObjectJSC(_value); + return new NSJSBase::CJSObjectJSC(_value); } inline JSValue* js_return(JSSmart _value) { - if (!_value.is_init()) - return nil; - NSJSBase::CJSValueJSC* _tmp = (NSJSBase::CJSValueJSC*)(_value.operator ->()); - return _tmp->value; + if (!_value.is_init()) + return nil; + NSJSBase::CJSValueJSC* _tmp = (NSJSBase::CJSValueJSC*)(_value.operator->()); + return _tmp->value; } -#define FUNCTION_WRAPPER_JS_0(NAME, NAME_EMBED) \ - -(JSValue*) NAME \ - { \ - return js_return(m_internal->NAME_EMBED()); \ - } +#define FUNCTION_WRAPPER_JS_0(NAME, NAME_EMBED) \ + -(JSValue*)NAME \ + { \ + return js_return(m_internal->NAME_EMBED()); \ + } #define FUNCTION_WRAPPER_JS(NAME, NAME_EMBED) FUNCTION_WRAPPER_JS_0(NAME, NAME_EMBED) -#define FUNCTION_WRAPPER_JS_1(NAME, NAME_EMBED) \ - -(JSValue*) NAME:(JSValue*)p1 \ - { \ - return js_return(m_internal->NAME_EMBED(js_value(p1))); \ - } -#define FUNCTION_WRAPPER_JS_2(NAME, NAME_EMBED) \ - -(JSValue*) NAME:(JSValue*)p1 : (JSValue*)p2 \ - { \ - return js_return(m_internal->NAME_EMBED(js_value(p1), js_value(p2))); \ - } -#define FUNCTION_WRAPPER_JS_3(NAME, NAME_EMBED) \ - -(JSValue*) NAME:(JSValue*)p1 : (JSValue*)p2 : (JSValue*)p3 \ - { \ - return js_return(m_internal->NAME_EMBED(js_value(p1), js_value(p2), js_value(p3))); \ - } -#define FUNCTION_WRAPPER_JS_4(NAME, NAME_EMBED) \ - -(JSValue*) NAME:(JSValue*)p1 : (JSValue*)p2 : (JSValue*)p3 : (JSValue*)p4 \ - { \ - return js_return(m_internal->NAME_EMBED(js_value(p1), js_value(p2), js_value(p3), js_value(p4))); \ - } -#define FUNCTION_WRAPPER_JS_5(NAME, NAME_EMBED) \ - -(JSValue*) NAME:(JSValue*)p1 : (JSValue*)p2 : (JSValue*)p3 : (JSValue*)p4 : (JSValue*)p5 \ - { \ - return js_return(m_internal->NAME_EMBED(js_value(p1), js_value(p2), js_value(p3), js_value(p4), js_value(p5))); \ - } -#define FUNCTION_WRAPPER_JS_6(NAME, NAME_EMBED) \ - -(JSValue*) NAME:(JSValue*)p1 : (JSValue*)p2 : (JSValue*)p3 : (JSValue*)p4 : (JSValue*)p5 : (JSValue*)p6 \ - { \ - return js_return(m_internal->NAME_EMBED(js_value(p1), js_value(p2), js_value(p3), js_value(p4), js_value(p5), js_value(p6))); \ - } -#define FUNCTION_WRAPPER_JS_7(NAME, NAME_EMBED) \ - -(JSValue*) NAME:(JSValue*)p1 : (JSValue*)p2 : (JSValue*)p3 : (JSValue*)p4 : (JSValue*)p5 : (JSValue*)p6 : (JSValue*)p7 \ - { \ - return js_return(m_internal->NAME_EMBED(js_value(p1), js_value(p2), js_value(p3), js_value(p4), js_value(p5), js_value(p6), js_value(p7))); \ - } -#define FUNCTION_WRAPPER_JS_8(NAME, NAME_EMBED) \ - -(JSValue*) NAME:(JSValue*)p1 : (JSValue*)p2 : (JSValue*)p3 : (JSValue*)p4 : (JSValue*)p5 : (JSValue*)p6 : (JSValue*)p7 : (JSValue*)p8 \ - { \ - return js_return(m_internal->NAME_EMBED(js_value(p1), js_value(p2), js_value(p3), js_value(p4), js_value(p5), js_value(p6), js_value(p7), js_value(p8))); \ - } +#define FUNCTION_WRAPPER_JS_1(NAME, NAME_EMBED) \ + -(JSValue*)NAME : (JSValue*)p1 \ + { \ + return js_return(m_internal->NAME_EMBED(js_value(p1))); \ + } +#define FUNCTION_WRAPPER_JS_2(NAME, NAME_EMBED) \ + -(JSValue*)NAME : (JSValue*)p1 : (JSValue*)p2 \ + { \ + return js_return(m_internal->NAME_EMBED(js_value(p1), js_value(p2))); \ + } +#define FUNCTION_WRAPPER_JS_3(NAME, NAME_EMBED) \ + -(JSValue*)NAME : (JSValue*)p1 : (JSValue*)p2 : (JSValue*)p3 \ + { \ + return js_return(m_internal->NAME_EMBED(js_value(p1), js_value(p2), js_value(p3))); \ + } +#define FUNCTION_WRAPPER_JS_4(NAME, NAME_EMBED) \ + -(JSValue*)NAME : (JSValue*)p1 : (JSValue*)p2 : (JSValue*)p3 : (JSValue*)p4 \ + { \ + return js_return(m_internal->NAME_EMBED(js_value(p1), js_value(p2), js_value(p3), js_value(p4))); \ + } +#define FUNCTION_WRAPPER_JS_5(NAME, NAME_EMBED) \ + -(JSValue*)NAME : (JSValue*)p1 : (JSValue*)p2 : (JSValue*)p3 : (JSValue*)p4 : (JSValue*)p5 \ + { \ + return js_return(m_internal->NAME_EMBED(js_value(p1), js_value(p2), js_value(p3), js_value(p4), js_value(p5))); \ + } +#define FUNCTION_WRAPPER_JS_6(NAME, NAME_EMBED) \ + -(JSValue*)NAME : (JSValue*)p1 : (JSValue*)p2 : (JSValue*)p3 : (JSValue*)p4 : (JSValue*)p5 : (JSValue*)p6 \ + { \ + return js_return(m_internal->NAME_EMBED(js_value(p1), js_value(p2), js_value(p3), js_value(p4), js_value(p5), js_value(p6))); \ + } +#define FUNCTION_WRAPPER_JS_7(NAME, NAME_EMBED) \ + -(JSValue*)NAME : (JSValue*)p1 : (JSValue*)p2 : (JSValue*)p3 : (JSValue*)p4 : (JSValue*)p5 : (JSValue*)p6 : (JSValue*)p7 \ + { \ + return js_return(m_internal->NAME_EMBED(js_value(p1), js_value(p2), js_value(p3), js_value(p4), js_value(p5), js_value(p6), js_value(p7))); \ + } +#define FUNCTION_WRAPPER_JS_8(NAME, NAME_EMBED) \ + -(JSValue*)NAME : (JSValue*)p1 : (JSValue*)p2 : (JSValue*)p3 : (JSValue*)p4 : (JSValue*)p5 : (JSValue*)p6 : (JSValue*)p7 : (JSValue*)p8 \ + { \ + return js_return(m_internal->NAME_EMBED(js_value(p1), js_value(p2), js_value(p3), js_value(p4), js_value(p5), js_value(p6), js_value(p7), js_value(p8))); \ + } #endif // _BUILD_NATIVE_CONTROL_JSC_BASE_H_ diff --git a/DesktopEditor/doctrenderer/js_internal/jsc/jsc_base.mm b/DesktopEditor/doctrenderer/js_internal/jsc/jsc_base.mm index 504aec74bf..fb8a097e73 100644 --- a/DesktopEditor/doctrenderer/js_internal/jsc/jsc_base.mm +++ b/DesktopEditor/doctrenderer/js_internal/jsc/jsc_base.mm @@ -6,436 +6,437 @@ using namespace NSJSBase; class CGlobalContext { private: - // считаем, что vector будет небольшим, поэтому он будет быстрее, чем map - std::vector> m_contexts; - bool m_bIsOldVersion; + // считаем, что vector будет небольшим, поэтому он будет быстрее, чем map + std::vector> m_contexts; + bool m_bIsOldVersion; - CGlobalContext() - { - m_bIsOldVersion = false; - #ifndef _IOS - if (@available(macOS 10.12, *)) - { - // none - } - else - { - m_bIsOldVersion = true; - } - #endif - } - ~CGlobalContext() - { - for (std::vector>::iterator i = m_contexts.begin(); i != m_contexts.end(); i++) - { - CJSContextPrivate* ctx = i->second; - delete ctx; - } - m_contexts.clear(); - } + CGlobalContext() + { + m_bIsOldVersion = false; +#ifndef _IOS + if (@available(macOS 10.12, *)) + { + // none + } + else + { + m_bIsOldVersion = true; + } +#endif + } + ~CGlobalContext() + { + for (std::vector>::iterator i = m_contexts.begin(); i != m_contexts.end(); i++) + { + CJSContextPrivate* ctx = i->second; + delete ctx; + } + m_contexts.clear(); + } public: - bool RegisterContext(CJSContextPrivate* ctx, ASC_THREAD_ID* id = NULL) - { - ASC_THREAD_ID nCurrentThread = (id == NULL) ? NSThreads::GetCurrentThreadId() : *id; - for (std::vector>::const_iterator i = m_contexts.begin(); i != m_contexts.end(); i++) - { - if (i->first == nCurrentThread) - { - return false; - } - } + bool RegisterContext(CJSContextPrivate* ctx, ASC_THREAD_ID* id = NULL) + { + ASC_THREAD_ID nCurrentThread = (id == NULL) ? NSThreads::GetCurrentThreadId() : *id; + for (std::vector>::const_iterator i = m_contexts.begin(); i != m_contexts.end(); i++) + { + if (i->first == nCurrentThread) + { + return false; + } + } - CJSContextPrivate* pContext = new CJSContextPrivate(); - pContext->context = ctx->context; - m_contexts.push_back(std::pair(nCurrentThread, pContext)); - return true; - } - void UnregisterContextForId(ASC_THREAD_ID nCurrentThread) - { - for (std::vector>::iterator i = m_contexts.begin(); i != m_contexts.end(); i++) - { - if (i->first == nCurrentThread) - { - CJSContextPrivate* ctx = i->second; - delete ctx; + CJSContextPrivate* pContext = new CJSContextPrivate(); + pContext->context = ctx->context; + m_contexts.push_back(std::pair(nCurrentThread, pContext)); + return true; + } + void UnregisterContextForId(ASC_THREAD_ID nCurrentThread) + { + for (std::vector>::iterator i = m_contexts.begin(); i != m_contexts.end(); i++) + { + if (i->first == nCurrentThread) + { + CJSContextPrivate* ctx = i->second; + delete ctx; - m_contexts.erase(i); - return; - } - } - } - void UnregisterContext() - { - UnregisterContextForId(NSThreads::GetCurrentThreadId()); - } + m_contexts.erase(i); + return; + } + } + } + void UnregisterContext() + { + UnregisterContextForId(NSThreads::GetCurrentThreadId()); + } - bool IsOldVersion() - { - return m_bIsOldVersion; - } + bool IsOldVersion() + { + return m_bIsOldVersion; + } - JSContext* GetCurrent() - { - ASC_THREAD_ID nCurrentThread = NSThreads::GetCurrentThreadId(); - for (std::vector>::const_iterator i = m_contexts.begin(); i != m_contexts.end(); i++) - { - if (i->first == nCurrentThread) - { - return i->second->context; - } - } - return [JSContext currentContext]; - } + JSContext* GetCurrent() + { + ASC_THREAD_ID nCurrentThread = NSThreads::GetCurrentThreadId(); + for (std::vector>::const_iterator i = m_contexts.begin(); i != m_contexts.end(); i++) + { + if (i->first == nCurrentThread) + { + return i->second->context; + } + } + return [JSContext currentContext]; + } - static CGlobalContext& GetInstance() - { - static CGlobalContext instance; - return instance; - } + static CGlobalContext& GetInstance() + { + static CGlobalContext instance; + return instance; + } }; JSContext* CJSContextPrivate::GetCurrentContext() { - return CGlobalContext::GetInstance().GetCurrent(); + return CGlobalContext::GetInstance().GetCurrent(); } bool CJSContextPrivate::IsOldVersion() { - return CGlobalContext::GetInstance().IsOldVersion(); + return CGlobalContext::GetInstance().IsOldVersion(); } -template +template bool CJSValueJSCTemplate::isUndefined() { - return (value == nil) ? true : ([value isUndefined] == YES); + return (value == nil) ? true : ([value isUndefined] == YES); } -template +template bool CJSValueJSCTemplate::isNull() { - return (value == nil) ? false : ([value isNull] == YES); + return (value == nil) ? false : ([value isNull] == YES); } -template +template bool CJSValueJSCTemplate::isBool() { - return (value == nil) ? false : ([value isBoolean] == YES); + return (value == nil) ? false : ([value isBoolean] == YES); } -template +template bool CJSValueJSCTemplate::isNumber() { - return (value == nil) ? false : ([value isNumber] == YES); + return (value == nil) ? false : ([value isNumber] == YES); } -template +template bool CJSValueJSCTemplate::isString() { - return (value == nil) ? false : ([value isString] == YES); + return (value == nil) ? false : ([value isString] == YES); } -template +template bool CJSValueJSCTemplate::isArray() { - return (value == nil) ? false : JSValueIsArray(getContext().JSGlobalContextRef, value.JSValueRef); + return (value == nil) ? false : JSValueIsArray(getContext().JSGlobalContextRef, value.JSValueRef); } -template +template bool CJSValueJSCTemplate::isTypedArray() { - return (value == nil) ? false : (kJSTypedArrayTypeNone != JSValueGetTypedArrayType(getContext().JSGlobalContextRef, value.JSValueRef, NULL)); + return (value == nil) ? false : (kJSTypedArrayTypeNone != JSValueGetTypedArrayType(getContext().JSGlobalContextRef, value.JSValueRef, NULL)); } -template +template bool CJSValueJSCTemplate::isObject() { - return (value == nil) ? false : ([value isObject] == YES); + return (value == nil) ? false : ([value isObject] == YES); } -template +template bool CJSValueJSCTemplate::isFunction() { - return isObject(); + return isObject(); } -template +template bool CJSValueJSCTemplate::isEmpty() { - return (value == nil) ? true : false; + return (value == nil) ? true : false; } -template +template void CJSValueJSCTemplate::doUndefined() { - value = [JSValue valueWithUndefinedInContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; + value = [JSValue valueWithUndefinedInContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; } -template +template void CJSValueJSCTemplate::doNull() { - value = [JSValue valueWithNullInContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; + value = [JSValue valueWithNullInContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; } -template +template bool CJSValueJSCTemplate::toBool() { - return ([value toBool] == YES) ? true : false; + return ([value toBool] == YES) ? true : false; } -template +template int CJSValueJSCTemplate::toInt32() { - return [value toInt32]; + return [value toInt32]; } -template +template unsigned int CJSValueJSCTemplate::toUInt32() { - return [value toUInt32]; + return [value toUInt32]; } -template +template double CJSValueJSCTemplate::toDouble() { - return [value toDouble]; + return [value toDouble]; } -template +template std::string CJSValueJSCTemplate::toStringA() { - return [[value toString] stdstring]; + return [[value toString] stdstring]; } -template +template std::wstring CJSValueJSCTemplate::toStringW() { - return [[value toString] stdwstring]; + return [[value toString] stdwstring]; } namespace NSJSBase { - CJSContext::CJSContext(const bool& bIsInitialize) - { - m_internal = new CJSContextPrivate(); - if (bIsInitialize) - Initialize(); - } - CJSContext::~CJSContext() - { - m_internal->context = nil; - RELEASEOBJECT(m_internal); - } + CJSContext::CJSContext(const bool& bIsInitialize) + { + m_internal = new CJSContextPrivate(); + if (bIsInitialize) + Initialize(); + } + CJSContext::~CJSContext() + { + if (m_internal->context) + Dispose(); + RELEASEOBJECT(m_internal); + } JSSmart CJSContext::GetExceptions() - { - return new CJSCTryCatch(); - } + { + return new CJSCTryCatch(); + } - void CJSContext::Initialize() - { - m_internal->context = [[JSContext alloc] init]; + void CJSContext::Initialize() + { + m_internal->context = [[JSContext alloc] init]; - ASC_THREAD_ID nThreadId = NSThreads::GetCurrentThreadId(); - MoveToThread(&nThreadId); - if (CGlobalContext::GetInstance().IsOldVersion()) - { - [m_internal->context evaluateScript:@"function jsc_toBase64(r){for(var o=[\"A\",\"B\",\"C\",\"D\",\"E\",\"F\",\"G\",\"H\",\"I\",\"J\",\"K\",\"L\",\"M\",\"N\",\"O\",\"P\",\"Q\",\"R\",\"S\",\"T\",\"U\",\"V\",\"W\",\"X\",\"Y\",\"Z\",\"a\",\"b\",\"c\",\"d\",\"e\",\"f\",\"g\",\"h\",\"i\",\"j\",\"k\",\"l\",\"m\",\"n\",\"o\",\"p\",\"q\",\"r\",\"s\",\"t\",\"u\",\"v\",\"w\",\"x\",\"y\",\"z\",\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"+\",\"/\"],a=r.length,f=4*(a/3>>0),n=f/76>>0,t=19,v=0,e=[],i=\"\",s=0;s<=n;s++){s==n&&(t=f%76/4>>0);for(var u=0;u>>26&255],c<<=6,c&=4294967295}e.push(i)}}if(n=a%3!=0?a%3+1:0){for(c=0,h=0;h<3;h++)h>>26&255],c<<=6}t=0!=n?4-n:0;for(u=0;u>>3,c=0;c>>16,s<<=8}return t}\n"]; - } + ASC_THREAD_ID nThreadId = NSThreads::GetCurrentThreadId(); + MoveToThread(&nThreadId); + if (CGlobalContext::GetInstance().IsOldVersion()) + { + [m_internal->context evaluateScript:@"function jsc_toBase64(r){for(var o=[\"A\",\"B\",\"C\",\"D\",\"E\",\"F\",\"G\",\"H\",\"I\",\"J\",\"K\",\"L\",\"M\",\"N\",\"O\",\"P\",\"Q\",\"R\",\"S\",\"T\",\"U\",\"V\",\"W\",\"X\",\"Y\",\"Z\",\"a\",\"b\",\"c\",\"d\",\"e\",\"f\",\"g\",\"h\",\"i\",\"j\",\"k\",\"l\",\"m\",\"n\",\"o\",\"p\",\"q\",\"r\",\"s\",\"t\",\"u\",\"v\",\"w\",\"x\",\"y\",\"z\",\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"+\",\"/\"],a=r.length,f=4*(a/3>>0),n=f/76>>0,t=19,v=0,e=[],i=\"\",s=0;s<=n;s++){s==n&&(t=f%76/4>>0);for(var u=0;u>>26&255],c<<=6,c&=4294967295}e.push(i)}}if(n=a%3!=0?a%3+1:0){for(c=0,h=0;h<3;h++)h>>26&255],c<<=6}t=0!=n?4-n:0;for(u=0;u>>3,c=0;c>>16,s<<=8}return t}\n"]; + } // insert CreateEmbedObject() function to global object of this context m_internal->context[@"CreateEmbedObject"] = ^(NSString* name) { return CreateEmbedNativeObject(name); }; - JSValue* global_js = [m_internal->context globalObject]; - [global_js setValue:global_js forProperty:[[NSString alloc] initWithUTF8String:"window"]]; - } - void CJSContext::Dispose() - { - for (std::vector::const_iterator i = m_internal->m_arThreads.begin(); i != m_internal->m_arThreads.end(); i++) - { - CGlobalContext::GetInstance().UnregisterContextForId(*i); - } - m_internal->context = nil; - } + JSValue* global_js = [m_internal->context globalObject]; + [global_js setValue:global_js forProperty:[[NSString alloc] initWithUTF8String:"window"]]; + } + void CJSContext::Dispose() + { + for (std::vector::const_iterator i = m_internal->m_arThreads.begin(); i != m_internal->m_arThreads.end(); i++) + { + CGlobalContext::GetInstance().UnregisterContextForId(*i); + } + m_internal->context = nil; + } JSSmart CJSContext::GetGlobal() - { - CJSObjectJSC* ret = new CJSObjectJSC(); - ret->value = [m_internal->context globalObject]; - return ret; - } + { + CJSObjectJSC* ret = new CJSObjectJSC(); + ret->value = [m_internal->context globalObject]; + return ret; + } - CJSValue* CJSContext::createUndefined() - { - CJSValueJSC* _value = new CJSValueJSC(); - _value->doUndefined(); - return _value; - } + CJSValue* CJSContext::createUndefined() + { + CJSValueJSC* _value = new CJSValueJSC(); + _value->doUndefined(); + return _value; + } - CJSValue* CJSContext::createNull() - { - CJSValueJSC* _value = new CJSValueJSC(); - _value->doNull(); - return _value; - } + CJSValue* CJSContext::createNull() + { + CJSValueJSC* _value = new CJSValueJSC(); + _value->doNull(); + return _value; + } - CJSValue* CJSContext::createBool(const bool& value) - { - CJSValueJSC* _value = new CJSValueJSC(); - _value->value = [JSValue valueWithBool:(value ? YES : NO) inContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; - return _value; - } + CJSValue* CJSContext::createBool(const bool& value) + { + CJSValueJSC* _value = new CJSValueJSC(); + _value->value = [JSValue valueWithBool:(value ? YES : NO) inContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; + return _value; + } - CJSValue* CJSContext::createInt(const int& value) - { - CJSValueJSC* _value = new CJSValueJSC(); - _value->value = [JSValue valueWithInt32:((int32_t) value) inContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; - return _value; - } + CJSValue* CJSContext::createInt(const int& value) + { + CJSValueJSC* _value = new CJSValueJSC(); + _value->value = [JSValue valueWithInt32:((int32_t)value) inContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; + return _value; + } - CJSValue* CJSContext::createUInt(const unsigned int& value) - { - CJSValueJSC* _value = new CJSValueJSC(); - _value->value = [JSValue valueWithUInt32:((uint32_t) value) inContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; - return _value; - } + CJSValue* CJSContext::createUInt(const unsigned int& value) + { + CJSValueJSC* _value = new CJSValueJSC(); + _value->value = [JSValue valueWithUInt32:((uint32_t)value) inContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; + return _value; + } - CJSValue* CJSContext::createDouble(const double& value) - { - CJSValueJSC* _value = new CJSValueJSC(); - _value->value = [JSValue valueWithDouble:value inContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; - return _value; - } + CJSValue* CJSContext::createDouble(const double& value) + { + CJSValueJSC* _value = new CJSValueJSC(); + _value->value = [JSValue valueWithDouble:value inContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; + return _value; + } - CJSValue* CJSContext::createString(const char* value, const int& len) - { - CJSValueJSC* _value = new CJSValueJSC(); - _value->value = [NSString stringWithUtf8Buffer:value length:(size_t)((len == -1) ? strlen(value) : len)]; - return _value; - } + CJSValue* CJSContext::createString(const char* value, const int& len) + { + CJSValueJSC* _value = new CJSValueJSC(); + _value->value = [JSValue valueWithObject:[NSString stringWithUtf8Buffer:value length:(size_t)((len == -1) ? strlen(value) : len)] inContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; + return _value; + } - CJSValue* CJSContext::createString(const wchar_t* value, const int& length) - { - std::string sUtf8 = NSFile::CUtf8Converter::GetUtf8StringFromUnicode2(value, (length != -1) ? (LONG)length : (LONG)wcslen(value)); - return createString((const char*)sUtf8.c_str(), (int)sUtf8.length()); - } + CJSValue* CJSContext::createString(const wchar_t* value, const int& length) + { + std::string sUtf8 = NSFile::CUtf8Converter::GetUtf8StringFromUnicode2(value, (length != -1) ? (LONG)length : (LONG)wcslen(value)); + return createString((const char*)sUtf8.c_str(), (int)sUtf8.length()); + } - CJSValue* CJSContext::createString(const std::string& value) - { - CJSValueJSC* _value = new CJSValueJSC(); - _value->value = [NSString stringWithAString:value]; - return _value; - } + CJSValue* CJSContext::createString(const std::string& value) + { + CJSValueJSC* _value = new CJSValueJSC(); + _value->value = [JSValue valueWithObject:[NSString stringWithAString:value] inContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; + return _value; + } - CJSValue* CJSContext::createString(const std::wstring& value) - { - CJSValueJSC* _value = new CJSValueJSC(); - _value->value = [NSString stringWithWString:value]; - return _value; - } + CJSValue* CJSContext::createString(const std::wstring& value) + { + CJSValueJSC* _value = new CJSValueJSC(); + _value->value = [JSValue valueWithObject:[NSString stringWithWString:value] inContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; + return _value; + } - CJSObject* CJSContext::createObject() - { - CJSObjectJSC* _value = new CJSObjectJSC(); - _value->value = [JSValue valueWithNewObjectInContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; - return _value; - } + CJSObject* CJSContext::createObject() + { + CJSObjectJSC* _value = new CJSObjectJSC(); + _value->value = [JSValue valueWithNewObjectInContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; + return _value; + } - CJSArray* CJSContext::createArray(const int& count) - { - CJSArrayJSC* _value = new CJSArrayJSC(); - _value->value = [JSValue valueWithNewArrayInContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; - return _value; - } + CJSArray* CJSContext::createArray(const int& count) + { + CJSArrayJSC* _value = new CJSArrayJSC(); + _value->value = [JSValue valueWithNewArrayInContext:NSJSBase::CJSContextPrivate::GetCurrentContext()]; + return _value; + } - CJSTypedArray* CJSContext::createUint8Array(BYTE* data, int count, const bool& isExternalize) - { - JSContext* _current = NSJSBase::CJSContextPrivate::GetCurrentContext(); - CJSTypedArrayJSC* _value = new CJSTypedArrayJSC(_current, data, count, isExternalize); - return _value; - } + CJSTypedArray* CJSContext::createUint8Array(BYTE* data, int count, const bool& isExternalize) + { + JSContext* _current = NSJSBase::CJSContextPrivate::GetCurrentContext(); + CJSTypedArrayJSC* _value = new CJSTypedArrayJSC(_current, data, count, isExternalize); + return _value; + } - JSSmart CJSContext::runScript(const std::string& script, JSSmart exception, const std::wstring& scriptPath) - { - CJSValueJSC* _value = new CJSValueJSC(); - _value->value = [m_internal->context evaluateScript:[NSString stringWithAString:script]]; - return _value; - } + JSSmart CJSContext::runScript(const std::string& script, JSSmart exception, const std::wstring& scriptPath) + { + CJSValueJSC* _value = new CJSValueJSC(); + _value->value = [m_internal->context evaluateScript:[NSString stringWithAString:script]]; + return _value; + } - unsigned char* NSAllocator::Alloc(const size_t& size) - { - return (unsigned char*)malloc(size); - } - void NSAllocator::Free(unsigned char* data, const size_t& size) - { - free(data); - } + unsigned char* NSAllocator::Alloc(const size_t& size) + { + return (unsigned char*)malloc(size); + } + void NSAllocator::Free(unsigned char* data, const size_t& size) + { + free(data); + } - JSSmart CJSContext::GetCurrent() - { - CJSContext* ret = new CJSContext(); - ret->m_internal->context = NSJSBase::CJSContextPrivate::GetCurrentContext(); - return ret; - } + JSSmart CJSContext::GetCurrent() + { + CJSContext* ret = new CJSContext(); + ret->m_internal->context = NSJSBase::CJSContextPrivate::GetCurrentContext(); + return ret; + } - void CJSContext::ExternalInitialize(const std::wstring& sDirectory) - { - } - void CJSContext::ExternalDispose() - { - } - bool CJSContext::IsSupportNativeTypedArrays() - { - return (CJSContextPrivate::IsOldVersion() == false) ? true : false; - } + void CJSContext::ExternalInitialize(const std::wstring& sDirectory) + { + } + void CJSContext::ExternalDispose() + { + } + bool CJSContext::IsSupportNativeTypedArrays() + { + return (CJSContextPrivate::IsOldVersion() == false) ? true : false; + } - JSSmart CJSContext::JSON_Parse(const char *sTmp) - { - if (!sTmp) - return CJSContext::createUndefined(); + JSSmart CJSContext::JSON_Parse(const char* sTmp) + { + if (!sTmp) + return CJSContext::createUndefined(); - NSString* sValue = [[NSString alloc] initWithUTF8String:sTmp]; - JSStringRef sValueRef = JSStringCreateWithCFString((__bridge CFStringRef)sValue); - JSValueRef oValueJSRef = JSValueMakeFromJSONString(m_internal->context.JSGlobalContextRef, sValueRef); + NSString* sValue = [[NSString alloc] initWithUTF8String:sTmp]; + JSStringRef sValueRef = JSStringCreateWithCFString((__bridge CFStringRef)sValue); + JSValueRef oValueJSRef = JSValueMakeFromJSONString(m_internal->context.JSGlobalContextRef, sValueRef); - CJSValueJSC* _value = new CJSValueJSC(); - _value->value = [JSValue valueWithJSValueRef:oValueJSRef inContext: m_internal->context]; - return _value; - } + CJSValueJSC* _value = new CJSValueJSC(); + _value->value = [JSValue valueWithJSValueRef:oValueJSRef inContext:m_internal->context]; + return _value; + } - void CJSContext::MoveToThread(ASC_THREAD_ID* id) - { - if (CGlobalContext::GetInstance().RegisterContext(m_internal, id)) - { - m_internal->m_arThreads.push_back((NULL == id) ? NSThreads::GetCurrentThreadId() : *id); - } - } + void CJSContext::MoveToThread(ASC_THREAD_ID* id) + { + if (CGlobalContext::GetInstance().RegisterContext(m_internal, id)) + { + m_internal->m_arThreads.push_back((NULL == id) ? NSThreads::GetCurrentThreadId() : *id); + } + } - void CJSContext::Enter() - { - } + void CJSContext::Enter() + { + } - void CJSContext::Exit() - { - } + void CJSContext::Exit() + { + } - class CJSLocalScopePrivate - { - public: - CJSLocalScopePrivate() - { - } - ~CJSLocalScopePrivate() - { - } - }; - CJSLocalScope::CJSLocalScope() : m_internal(nullptr) - { - } + class CJSLocalScopePrivate + { + public: + CJSLocalScopePrivate() + { + } + ~CJSLocalScopePrivate() + { + } + }; + CJSLocalScope::CJSLocalScope() : m_internal(nullptr) + { + } - CJSLocalScope::~CJSLocalScope() - { - } + CJSLocalScope::~CJSLocalScope() + { + } } namespace NSJSBase { - bool CJSCTryCatch::Check() - { - JSValue* exc = [context exception]; - if (exc == nil || [exc isNull] || [exc isUndefined]) - return false; + bool CJSCTryCatch::Check() + { + JSValue* exc = [context exception]; + if (exc == nil || [exc isNull] || [exc isUndefined]) + return false; - NSString* pExсeption = [exc toString]; - std::cerr << [pExсeption stdstring] << std::endl; - NSLog(@"%@", pExсeption); + NSString* pExсeption = [exc toString]; + std::cerr << [pExсeption stdstring] << std::endl; + NSLog(@"%@", pExсeption); - exc = nil; - return true; - } + exc = nil; + return true; + } } // embed diff --git a/DesktopEditor/doctrenderer/js_internal/v8/v8_base.h b/DesktopEditor/doctrenderer/js_internal/v8/v8_base.h index c90f2966d4..01c6d1bc37 100644 --- a/DesktopEditor/doctrenderer/js_internal/v8/v8_base.h +++ b/DesktopEditor/doctrenderer/js_internal/v8/v8_base.h @@ -425,9 +425,9 @@ namespace NSJSBase return _value; } - virtual void set(const char* name, CJSValue* value_param) + virtual void set(const char* name, JSSmart value_param) { - CJSValueV8* _value = static_cast(value_param); + CJSValueV8* _value = static_cast(value_param.GetPointer()); v8::Local _name = CreateV8String(CV8Worker::GetCurrent(), name); value->Set(V8ContextFirstArg _name, _value->value); } @@ -446,6 +446,28 @@ namespace NSJSBase value->Set(V8ContextFirstArg _name, v8::Number::New(isolate, _value)); } + virtual std::vector getPropertyNames() + { + v8::Local context = CV8Worker::GetCurrentContext(); + v8::Local names = value->GetPropertyNames(context).ToLocalChecked(); + uint32_t len = names->Length(); + + std::vector ret; + for (uint32_t i = 0; i < len; i++) + { + v8::Local propertyName = names->Get(context, i).ToLocalChecked(); + v8::Local propertyValue = value->Get(context, propertyName).ToLocalChecked(); + // skip undefined properties + if (propertyValue->IsUndefined()) + continue; + CJSValueV8 _value; + _value.value = propertyName; + ret.push_back(_value.toStringA()); + } + + return ret; + } + virtual CJSEmbedObject* getNative() { v8::Handle field = v8::Handle::Cast(value->GetInternalField(0)); @@ -530,23 +552,18 @@ namespace NSJSBase return _value; } - virtual void set(const int& index, CJSValue* value_param) + virtual void set(const int& index, JSSmart value_param) { - CJSValueV8* _value = static_cast(value_param); + CJSValueV8* _value = static_cast(value_param.GetPointer()); value->Set(V8ContextFirstArg index, _value->value); } - virtual void add(CJSValue* value_param) + virtual void add(JSSmart value_param) { - CJSValueV8* _value = static_cast(value_param); + CJSValueV8* _value = static_cast(value_param.GetPointer()); value->Set(V8ContextFirstArg getCount(), _value->value); } - virtual void set(const int& index, const bool& _value) - { - value->Set(V8ContextFirstArg index, v8::Boolean::New(CV8Worker::GetCurrent(), _value)); - } - virtual void set(const int& index, const int& _value) { value->Set(V8ContextFirstArg index, v8::Integer::New(CV8Worker::GetCurrent(), _value)); diff --git a/DesktopEditor/doctrenderer/json/json.cpp b/DesktopEditor/doctrenderer/json/json.cpp new file mode 100644 index 0000000000..96cc8bef95 --- /dev/null +++ b/DesktopEditor/doctrenderer/json/json.cpp @@ -0,0 +1,420 @@ +#include "json.h" +#include "json_p.h" +#include "json_values.h" + +// for working with typed arrays: Alloc() and Free() +#include "js_base.h" + +namespace NSJSON +{ + CTypedValue::CTypedValue() : m_type(vtUndefined) + { + } + + CTypedValue::CTypedValue(IBaseValue* value, ValueType type) : m_value(value), m_type(type) + { + } + + CTypedValue::~CTypedValue() + { + } + + + IValue::IValue() : m_internal(new CTypedValue()) + { + } + + IValue::IValue(const std::shared_ptr& internal) : m_internal(internal) + { + } + + IValue::~IValue() + { + } + + bool IValue::IsUndefined() const + { + return m_internal->m_type == CTypedValue::vtUndefined; + } + + bool IValue::IsNull() const + { + return m_internal->m_type == CTypedValue::vtNull; + } + + bool IValue::IsBool() const + { + return (m_internal->m_type == CTypedValue::vtPrimitive && + static_cast(m_internal->m_value.get())->isBool()); + } + + bool IValue::IsInt() const + { + return (m_internal->m_type == CTypedValue::vtPrimitive && + static_cast(m_internal->m_value.get())->isInt()); + } + + bool IValue::IsDouble() const + { + return (m_internal->m_type == CTypedValue::vtPrimitive && + static_cast(m_internal->m_value.get())->isDouble()); + } + + bool IValue::IsStringA() const + { + return (m_internal->m_type == CTypedValue::vtPrimitive && + static_cast(m_internal->m_value.get())->isStringA()); + } + + bool IValue::IsStringW() const + { + return (m_internal->m_type == CTypedValue::vtPrimitive && + static_cast(m_internal->m_value.get())->isStringW()); + } + + bool IValue::IsArray() const + { + return m_internal->m_type == CTypedValue::vtArray; + } + + bool IValue::IsTypedArray() const + { + return m_internal->m_type == CTypedValue::vtTypedArray; + } + + bool IValue::IsObject() const + { + return m_internal->m_type == CTypedValue::vtObject; + } + + bool IValue::ToBool() const + { + if (m_internal->m_type != CTypedValue::vtPrimitive) + { +#ifdef JSON_DEBUG + throw std::bad_cast(); +#endif + return false; + } + return static_cast(m_internal->m_value.get())->toBool(); + } + + int IValue::ToInt() const + { + if (m_internal->m_type != CTypedValue::vtPrimitive) + { +#ifdef JSON_DEBUG + throw std::bad_cast(); +#endif + return 0; + } + return static_cast(m_internal->m_value.get())->toInt(); + } + + double IValue::ToDouble() const + { + if (m_internal->m_type != CTypedValue::vtPrimitive) + { +#ifdef JSON_DEBUG + throw std::bad_cast(); +#endif + return 0.0; + } + return static_cast(m_internal->m_value.get())->toDouble(); + } + + std::string IValue::ToStringA() const + { + if (m_internal->m_type != CTypedValue::vtPrimitive) + { +#ifdef JSON_DEBUG + throw std::bad_cast(); +#endif + return ""; + } + return static_cast(m_internal->m_value.get())->toStringA(); + } + + std::wstring IValue::ToStringW() const + { + if (m_internal->m_type != CTypedValue::vtPrimitive) + { +#ifdef JSON_DEBUG + throw std::bad_cast(); +#endif + return L""; + } + return static_cast(m_internal->m_value.get())->toStringW(); + } + + IValue::operator bool() const + { + return ToBool(); + } + + IValue::operator int() const + { + return ToInt(); + } + + IValue::operator double() const + { + return ToDouble(); + } + + IValue::operator std::string() const + { + return ToStringA(); + } + + IValue::operator std::wstring() const + { + return ToStringW(); + } + + IValue::IValue(bool value) : m_internal(new CTypedValue(new CPrimitive(value), CTypedValue::vtPrimitive)) + { + } + + IValue::IValue(int value) : m_internal(new CTypedValue(new CPrimitive(value), CTypedValue::vtPrimitive)) + { + } + + IValue::IValue(double value) : m_internal(new CTypedValue(new CPrimitive(value), CTypedValue::vtPrimitive)) + { + } + + IValue::IValue(const char* value) : m_internal(new CTypedValue(new CPrimitive(std::string(value)), CTypedValue::vtPrimitive)) + { + } + + IValue::IValue(const std::string& value) : m_internal(new CTypedValue(new CPrimitive(value), CTypedValue::vtPrimitive)) + { + } + + IValue::IValue(const wchar_t* value) : m_internal(new CTypedValue(new CPrimitive(std::wstring(value)), CTypedValue::vtPrimitive)) + { + } + + IValue::IValue(const std::wstring& value) : m_internal(new CTypedValue(new CPrimitive(value), CTypedValue::vtPrimitive)) + { + } + + int IValue::GetCount() const + { + if (m_internal->m_type == CTypedValue::vtArray) + return static_cast(m_internal->m_value.get())->getCount(); + else if (m_internal->m_type == CTypedValue::vtTypedArray) + return static_cast(m_internal->m_value.get())->getCount(); + else + return 0; + } + + const CValueRef IValue::Get(int index) const + { + if (m_internal->m_type != CTypedValue::vtArray) + return CValue(); + if (index < 0 || index >= GetCount()) + return CValue(); + return static_cast(m_internal->m_value.get())->get(index); + } + + CValueRef IValue::Get(int index) + { + return static_cast(*this).Get(index); + } + + const CValueRef IValue::operator[](int index) const + { + return Get(index); + } + + CValueRef IValue::operator[](int index) + { + return Get(index); + } + + IValue::IValue(std::initializer_list elements) : m_internal(new CTypedValue(new CArray(elements), CTypedValue::vtArray)) + { + } + + const BYTE* IValue::GetData() const + { + if (m_internal->m_type != CTypedValue::vtTypedArray) + return nullptr; + return static_cast(m_internal->m_value.get())->getData(); + } + + BYTE* IValue::GetData() + { + return const_cast(static_cast(*this).GetData()); + } + + const CValueRef IValue::Get(const char* name) const + { + if (m_internal->m_type != CTypedValue::vtObject) + return CValue(); + return static_cast(m_internal->m_value.get())->get(name); + } + + CValueRef IValue::Get(const char* name) + { + return static_cast(*this).Get(name); + } + + const CValueRef IValue::operator[](const char* name) const + { + return Get(name); + } + + CValueRef IValue::operator[](const char* name) + { + return Get(name); + } + + std::vector IValue::GetPropertyNames() const + { + if (m_internal->m_type != CTypedValue::vtObject) + return {}; + return static_cast(m_internal->m_value.get())->getPropertyNames(); + } + + + CValue::CValue() : IValue() + { + } + + CValue::CValue(const CValue& other) : IValue(std::make_shared(*other.m_internal)) + { + } + + CValue::CValue(const CValueRef& ref) : IValue(std::make_shared(*ref.m_internal)) + { + } + + CValue::~CValue() + { + } + + CValue& CValue::operator=(const CValue& other) + { + *m_internal = *other.m_internal; + return *this; + } + + CValue& CValue::operator=(const CValueRef& ref) + { + *m_internal = *ref.m_internal; + return *this; + } + + CValue::CValue(bool value) : IValue(value) + { + } + + CValue::CValue(int value) : IValue(value) + { + } + + CValue::CValue(double value) : IValue(value) + { + } + + CValue::CValue(const char* value) : IValue(value) + { + } + + CValue::CValue(const std::string& value) : IValue(value) + { + } + + CValue::CValue(const wchar_t* value) : IValue(value) + { + } + + CValue::CValue(const std::wstring& value) : IValue(value) + { + } + + CValue::CValue(std::initializer_list elements) : IValue(elements) + { + } + + CValue CValue::CreateArray(int count) + { + CValue ret; + if (count < 0) + return ret; + + ret.m_internal->m_value = std::make_shared(count); + ret.m_internal->m_type = CTypedValue::vtArray; + return ret; + } + + CValue CValue::CreateTypedArray(BYTE* data, int count, bool isExternalize) + { + CValue ret; + if (count <= 0) + return ret; + + ret.m_internal->m_value = std::make_shared(data, count, isExternalize); + ret.m_internal->m_type = CTypedValue::vtTypedArray; + return ret; + } + + BYTE* CValue::AllocTypedArray(size_t size) + { + return NSJSBase::NSAllocator::Alloc(size); + } + + void CValue::FreeTypedArray(BYTE* data, size_t size) + { + NSJSBase::NSAllocator::Free(data, size); + } + + CValue CValue::CreateObject() + { + CValue ret; + ret.m_internal->m_value = std::make_shared(); + ret.m_internal->m_type = CTypedValue::vtObject; + return ret; + } + + CValue CValue::CreateUndefined() + { + return CValue(); + } + + CValue CValue::CreateNull() + { + CValue ret; + ret.m_internal->m_type = CTypedValue::vtNull; + return ret; + } + + CValueRef::CValueRef(const CValueRef& other) : IValue(other.m_internal) + { + } + + CValueRef::CValueRef(const CValue& value) : IValue(value.m_internal) + { + } + + CValueRef::~CValueRef() + { + } + + CValueRef& CValueRef::operator=(const CValueRef& other) + { + // not reassign the pointer, but copy its content! + *m_internal = *other.m_internal; + return *this; + } + + CValueRef& CValueRef::operator=(const CValue& value) + { + // not reassign the pointer, but copy its content! + *m_internal = *value.m_internal; + return *this; + } +} diff --git a/DesktopEditor/doctrenderer/json/json.h b/DesktopEditor/doctrenderer/json/json.h new file mode 100644 index 0000000000..fef572ead7 --- /dev/null +++ b/DesktopEditor/doctrenderer/json/json.h @@ -0,0 +1,274 @@ +#ifndef JSON_H_ +#define JSON_H_ + +#include +#include +#include +#include + +#ifdef JSBASE_NO_USE_DYNAMIC_LIBRARY +#define JSON_DECL +#else +#include "../../common/base_export.h" +#ifdef JSBASE_USE_DYNAMIC_LIBRARY_BUILDING +#define JSON_DECL Q_DECL_EXPORT +#else +#define JSON_DECL Q_DECL_IMPORT +#endif +#endif + +// uncomment to enable exceptions throwing +//#define JSON_DEBUG + +namespace NSJSON +{ + typedef unsigned char BYTE; + + class CValue; + class CValueRef; + class CTypedValue; + // Main value interface. + // This class provide interface to work with each type of values. + class JSON_DECL IValue + { + protected: + IValue(); + IValue(const std::shared_ptr& internal); + virtual ~IValue(); + + // Disable copy for this class (implemented in heirs) + IValue(const IValue& other) = delete; + IValue& operator=(const IValue& other) = delete; + + public: + // TYPE CHECKS + /** + * Returns true if the value is undefined. + */ + bool IsUndefined() const; + /** + * Returns true if the value is null. + */ + bool IsNull() const; + /** + * Returns true if the value is a boolean value. + */ + bool IsBool() const; + /** + * Returns true if the value is an integer. + */ + bool IsInt() const; + /** + * Returns true if the value is a double value. + */ + bool IsDouble() const; + /** + * Returns true if the value is a string. + */ + bool IsStringA() const; + /** + * Returns true if the value is a wstring. + */ + bool IsStringW() const; + /** + * Returns true if the value is an array. + */ + bool IsArray() const; + /** + * Returns true if the value is a typed array. + */ + bool IsTypedArray() const; + /** + * Returns true if the value is an object. + */ + bool IsObject() const; + + // FUNCTIONS FOR WORKING WITH PRIMITIVE VALUES + /** + * Converts this value to a boolean value. + * @returns Corresponding boolean value. If the value is not a boolean, returns false instead. + */ + bool ToBool() const; + /** + * Converts this value to an integer. + * @returns Corresponding integer value. If the value is not a number, returns 0 instead. + */ + int ToInt() const; + /** + * Converts this value to a double value. + * @returns Corresponding double value. If the value is not a number, returns 0.0 instead. + */ + double ToDouble() const; + /** + * Converts this value to a std::string. + * @returns Corresponding std::string. If the value is not a string, returns empty string instead. + */ + std::string ToStringA() const; + /** + * Converts this value to a wstring. + * @returns Corresponding std::wstring. If the value is not a string, returns empty string instead. + */ + std::wstring ToStringW() const; + + // Type cast operators work the same way as conversion functions + operator bool() const; + operator int() const; + operator double() const; + operator std::string() const; + operator std::wstring() const; + + protected: + // Creates a value from primitive types + IValue(bool value); + IValue(int value); + IValue(double value); + IValue(const char* value); + IValue(const std::string& value); + IValue(const wchar_t* value); + IValue(const std::wstring& value); + + public: + // FUNCTIONS FOR WORKING WITH ARRAYS + /** + * Gets lengths of the array/typed array. + * @returns Returns the number of elements in the array or number of bytes in typed array. If current value is not an array/typed array, returns 0. + */ + int GetCount() const; + + /** + * Gets an array value by its index. + * @param index The index of the array value. + * @returns the value in the array. If current value is not an array, returns undefined value. + */ + const CValueRef Get(int index) const; + CValueRef Get(int index); + + // operators [] works the same way as Get(index) + const CValueRef operator[](int index) const; + CValueRef operator[](int index); + + protected: + // create array from initializer list + IValue(std::initializer_list elements); + + public: + // FUNCTIONS FOR WORKING WITH TYPED ARRAYS + /** + * Gets data of typed array. + * @return the pointer to memory, allocated for this typed array. If current value is not a typed array, returns nullptr. + */ + const BYTE* GetData() const; + BYTE* GetData(); + + // FUNCTIONS FOR WORKING WITH OBJECTS + /** + * Gets a property of this object. + * @param name The name of the property. + * @returns the value of the object's property. If current value is not an object, returns undefined value. + */ + const CValueRef Get(const char* name) const; + CValueRef Get(const char* name); + + // operators [] works the same way as Get(name) + const CValueRef operator[](const char* name) const; + CValueRef operator[](const char* name); + + /** + * Retrieves all property names from current object. + * @returns a vector containing the names of the properties of this object as strings. If current value is not an object, returns an empty vector. + */ + std::vector GetPropertyNames() const; + + protected: + std::shared_ptr m_internal; + }; + + // Main value implementation + class JSON_DECL CValue : public IValue + { + public: + CValue(); + CValue(const CValue& other); + CValue(const CValueRef& ref); + ~CValue(); + + CValue& operator=(const CValue& other); + CValue& operator=(const CValueRef& ref); + + // PRIMITIVES CONSTRUCTORS + CValue(bool value); + CValue(int value); + CValue(double value); + CValue(const char* value); + CValue(const std::string& value); + CValue(const wchar_t* value); + CValue(const std::wstring& value); + + // ARRAY CONSTRUCTORS + /** + * Creates an array with initializer list syntax (CValue arr = {1, 2, 3}). + * @param elements The elements of an array as an std::initializer_list. + */ + CValue(std::initializer_list elements); + /** + * Creates and returns new array. + * @param count The number of elements reserved for the array. + */ + static CValue CreateArray(int count); + + // TYPED ARRAY + /** + * Creates and returns new typed array. + * @param data The pointer to binary data. The pointer should be acquired with AllocTypedArray()! + * @param count The length of an array in bytes. + * @param isExternalize If true the memory block will not be reclaimed when the created typed array is destroyed. + * If this parameter is false then the memory block will be released using FreeTypedArray() during the typed array destruction. + */ + static CValue CreateTypedArray(BYTE* data, int count, bool isExternalize = true); + /** + * Allocates the memory for a typed array by creating a buffer array of the specified size. + * @param size The buffer array size. + */ + static BYTE* AllocTypedArray(size_t size); + /** + * Frees the memory for a typed array. + * @param data The allocated memory to be released. + * @param size The buffer array size. + */ + static void FreeTypedArray(BYTE* data, size_t size); + + // OBJECT CONSTRUCTOR + /** + * Creates and returns empty object. + */ + static CValue CreateObject(); + + // OTHER FUNCTIONS + /** + * Creates and returns undefined value (the same as CValue()). + */ + static CValue CreateUndefined(); + /** + * Creates and returns null value. + */ + static CValue CreateNull(); + + friend class CValueRef; + }; + + // Main value reference implementation + class JSON_DECL CValueRef : public IValue + { + public: + CValueRef(const CValueRef& other); + CValueRef(const CValue& value); + ~CValueRef(); + + CValueRef& operator=(const CValueRef& other); + CValueRef& operator=(const CValue& value); + + friend class CValue; + }; +} + +#endif // JSON_H_ diff --git a/DesktopEditor/doctrenderer/json/json_p.h b/DesktopEditor/doctrenderer/json/json_p.h new file mode 100644 index 0000000000..0198a402d0 --- /dev/null +++ b/DesktopEditor/doctrenderer/json/json_p.h @@ -0,0 +1,37 @@ +#ifndef JSON_PRIVATE_H_ +#define JSON_PRIVATE_H_ + +#include + +namespace NSJSON +{ + class IBaseValue; + // Wrapper around IBaseValue with specific value type + class CTypedValue + { + public: + enum ValueType + { + vtUndefined, + vtNull, + vtPrimitive, + vtArray, + vtTypedArray, + vtObject + }; + + public: + CTypedValue(); + CTypedValue(IBaseValue* value, ValueType type); + ~CTypedValue(); + // default copy behaviour + CTypedValue(const CTypedValue& other) = default; + CTypedValue& operator=(const CTypedValue& other) = default; + + public: + std::shared_ptr m_value; + ValueType m_type; + }; +} + +#endif // JSON_PRIVATE_H_ diff --git a/DesktopEditor/doctrenderer/json/json_values.cpp b/DesktopEditor/doctrenderer/json/json_values.cpp new file mode 100644 index 0000000000..8b15705622 --- /dev/null +++ b/DesktopEditor/doctrenderer/json/json_values.cpp @@ -0,0 +1,199 @@ +#include "json_values.h" + +namespace NSJSON +{ + IBaseValue::IBaseValue() + { + } + + IBaseValue::~IBaseValue() + { + } + + CPrimitive::CPrimitive(bool value) : m_type(ptBoolean) + { + m_bool = value; + } + + CPrimitive::CPrimitive(int value) : m_type(ptInteger) + { + m_int = value; + } + + CPrimitive::CPrimitive(double value) : m_type(ptDouble) + { + m_double = value; + } + + CPrimitive::CPrimitive(const std::string& str) : m_type(ptStringA) + { + new (&m_string) std::string(str); + } + + CPrimitive::CPrimitive(const std::wstring& wstr) : m_type(ptStringW) + { + new (&m_wstring) std::wstring(wstr); + } + + CPrimitive::~CPrimitive() + { + switch (m_type) + { + case ptStringA: + m_string.~basic_string(); + break; + case ptStringW: + m_wstring.~basic_string(); + break; + default: + break; + } + } + + bool CPrimitive::isBool() const + { + return m_type == ptBoolean; + } + + bool CPrimitive::isInt() const + { + return m_type == ptInteger; + } + + bool CPrimitive::isDouble() const + { + return m_type == ptDouble; + } + + bool CPrimitive::isStringA() const + { + return m_type == ptStringA; + } + + bool CPrimitive::isStringW() const + { + return m_type == ptStringW; + } + + bool CPrimitive::toBool() const + { + if (m_type == ptBoolean) + return m_bool; +#ifdef JSON_DEBUG + throw std::bad_cast(); +#endif + return false; + } + + int CPrimitive::toInt() const + { + if (m_type == ptInteger) + return m_int; + if (m_type == ptDouble) + return (int)m_double; +#ifdef JSON_DEBUG + throw std::bad_cast(); +#endif + return 0; + } + + double CPrimitive::toDouble() const + { + if (m_type == ptDouble) + return m_double; + if (m_type == ptInteger) + return (double)m_int; +#ifdef JSON_DEBUG + throw std::bad_cast(); +#endif + return 0.0; + } + + std::string CPrimitive::toStringA() const + { + if (m_type == ptStringA) + return m_string; +#ifdef JSON_DEBUG + throw std::bad_cast(); +#endif + return ""; + } + + std::wstring CPrimitive::toStringW() const + { + if (m_type == ptStringW) + return m_wstring; +#ifdef JSON_DEBUG + throw std::bad_cast(); +#endif + return L""; + } + + CArray::CArray(int count) : m_values(count) + { + } + + CArray::CArray(std::initializer_list elements) : m_values(elements) + { + } + + CArray::~CArray() + { + } + + int CArray::getCount() const + { + return (int)m_values.size(); + } + + CValue& CArray::get(int index) + { + return m_values[index]; + } + + CTypedArray::CTypedArray(BYTE* data, int len, bool isExternalize) : m_data(data), m_len(len), m_isExternalize(isExternalize) + { + } + + CTypedArray::~CTypedArray() + { + if (!m_isExternalize) + { + CValue::FreeTypedArray(m_data, m_len); + } + } + + BYTE* CTypedArray::getData() + { + return m_data; + } + + int CTypedArray::getCount() const + { + return m_len; + } + + CObject::CObject() + { + } + + CObject::~CObject() + { + } + + CValue& CObject::get(const std::string& name) + { + return m_values[name]; + } + + std::vector CObject::getPropertyNames() + { + std::vector ret; + for (const storage_t::value_type& entry : m_values) + { + if (!entry.second.IsUndefined()) + ret.push_back(entry.first); + } + return ret; + } +} diff --git a/DesktopEditor/doctrenderer/json/json_values.h b/DesktopEditor/doctrenderer/json/json_values.h new file mode 100644 index 0000000000..e3c01ecaf4 --- /dev/null +++ b/DesktopEditor/doctrenderer/json/json_values.h @@ -0,0 +1,118 @@ +#ifndef JSON_VALUES_H_ +#define JSON_VALUES_H_ + +#include +#include +#include + +#include "json.h" + +namespace NSJSON +{ + class IBaseValue + { + public: + IBaseValue(); + virtual ~IBaseValue(); + }; + + class CPrimitive : public IBaseValue + { + private: + enum PrimitiveType + { + ptBoolean, + ptInteger, + ptDouble, + ptStringA, + ptStringW + }; + + public: + CPrimitive(bool value); + CPrimitive(int value); + CPrimitive(double value); + CPrimitive(const std::string& str); + CPrimitive(const std::wstring& wstr); + ~CPrimitive(); + + // disable copy + CPrimitive(const CPrimitive& other) = delete; + CPrimitive& operator=(const CPrimitive& other) = delete; + + // type check + bool isBool() const; + bool isInt() const; + bool isDouble() const; + bool isStringA() const; + bool isStringW() const; + + // getters + bool toBool() const; + int toInt() const; + double toDouble() const; + std::string toStringA() const; + std::wstring toStringW() const; + + private: + union + { + bool m_bool; + int m_int; + double m_double; + std::string m_string; + std::wstring m_wstring; + }; + PrimitiveType m_type; + }; + + class CArray : public IBaseValue + { + public: + CArray(int count); + CArray(std::initializer_list elements); + ~CArray(); + + public: + int getCount() const; + CValue& get(int index); + + private: + std::vector m_values; + }; + + class CTypedArray : public IBaseValue + { + public: + CTypedArray(BYTE* data, int len, bool isExternalize = true); + ~CTypedArray(); + + public: + BYTE* getData(); + int getCount() const; + + private: + BYTE* m_data; + int m_len; + bool m_isExternalize; + }; + + class CObject : public IBaseValue + { + private: + using storage_t = std::unordered_map; + + public: + CObject(); + ~CObject(); + + public: + CValue& get(const std::string& name); + std::vector getPropertyNames(); + + private: + storage_t m_values; + }; +} + +#endif // JSON_VALUES_H_ diff --git a/DesktopEditor/doctrenderer/json/serialization.h b/DesktopEditor/doctrenderer/json/serialization.h new file mode 100644 index 0000000000..844d625633 --- /dev/null +++ b/DesktopEditor/doctrenderer/json/serialization.h @@ -0,0 +1,149 @@ +#ifndef SERIALIZATION_H_ +#define SERIALIZATION_H_ + +#include "json.h" +#include "../js_internal/js_base.h" + +#include + +namespace NSJSON +{ + static JSSmart toJS(const CValue& value) + { + if (value.IsUndefined()) + return NSJSBase::CJSContext::createUndefined(); + if (value.IsNull()) + return NSJSBase::CJSContext::createNull(); + + JSSmart ret; + // handle primitive types first, as they are most commonly used + if (value.IsBool()) + { + ret = NSJSBase::CJSContext::createBool((bool)value); + } + else if (value.IsInt()) + { + ret = NSJSBase::CJSContext::createInt((int)value); + } + else if (value.IsDouble()) + { + ret = NSJSBase::CJSContext::createDouble((double)value); + } + else if (value.IsStringA()) + { + ret = NSJSBase::CJSContext::createString((std::string)value); + } + else if (value.IsStringW()) + { + ret = NSJSBase::CJSContext::createString((std::wstring)value); + } + // arrays + else if (value.IsArray()) + { + const int len = value.GetCount(); + JSSmart jsArr = NSJSBase::CJSContext::createArray(len); + for (int i = 0; i < len; i++) + { + jsArr->set(i, toJS(value[i])); + } + ret = jsArr->toValue(); + } + // typed arrays + else if (value.IsTypedArray()) + { + JSSmart jsTypedArr = NSJSBase::CJSContext::createUint8Array(const_cast(value.GetData()), value.GetCount()); + ret = jsTypedArr->toValue(); + } + // objects (there is no need for IsObject()) + else + { + JSSmart jsObj = NSJSBase::CJSContext::createObject(); + std::vector properties = value.GetPropertyNames(); + for (const std::string& name : properties) + { + JSSmart jsValue = toJS(value[name.c_str()]); + jsObj->set(name.c_str(), jsValue); + } + ret = jsObj->toValue(); + } + + return ret; + } + + static CValue fromJS(JSSmart jsValue) + { + if (jsValue->isUndefined()) + return CValue::CreateUndefined(); + if (jsValue->isNull()) + return CValue::CreateNull(); + + CValue ret; + // handle primitive types first, as they are most commonly used + if (jsValue->isBool()) + { + ret = CValue(jsValue->toBool()); + } + else if (jsValue->isNumber()) + { + double number = jsValue->toDouble(); + if (std::isfinite(number)) + { + // check if number is an integer or double + double integral; // integral part + double fractional = std::modf(number, &integral); // fractional part + // TODO: this may not work for non-32 bit integers + if (fractional == 0.0 && integral >= INT_MIN && integral <= INT_MAX) + ret = (int)integral; + else + ret = number; + } + else + { + // handle NaN, inf, -inf + ret = number; + } + } + else if (jsValue->isString()) + { + // convert all strings to std::wstring, because in JS all strings are encoded in UTF-16 + ret = jsValue->toStringW(); + } + // arrays + else if (jsValue->isArray()) + { + JSSmart jsArr = jsValue->toArray(); + const int len = jsArr->getCount(); + ret = CValue::CreateArray(len); + for (int i = 0; i < len; i++) + { + JSSmart jsElement = jsArr->get(i); + ret[i] = fromJS(jsElement); + } + } + // typed arrays + else if (jsValue->isTypedArray()) + { + JSSmart jsTypedArr = jsValue->toTypedArray(); + const int len = jsTypedArr->getCount(); + BYTE* data = jsTypedArr->getData().Data; + ret = CValue::CreateTypedArray(data, len); + } + // objects + else if (jsValue->isObject()) + { + JSSmart jsObj = jsValue->toObject(); + std::vector properties = jsObj->getPropertyNames(); + ret = CValue::CreateObject(); + for (const std::string& name : properties) + { + JSSmart jsPropertyValue = jsObj->get(name.c_str()); + ret[name.c_str()] = fromJS(jsPropertyValue); + } + } + // else the type is not supported and will be converted as undefined value + + return ret; + } +} + +#endif // SERIALIZATION_H_ diff --git a/DesktopEditor/doctrenderer/test/internal/Embed.cpp b/DesktopEditor/doctrenderer/test/embed/external/Embed.cpp similarity index 100% rename from DesktopEditor/doctrenderer/test/internal/Embed.cpp rename to DesktopEditor/doctrenderer/test/embed/external/Embed.cpp diff --git a/DesktopEditor/doctrenderer/test/internal/Embed.h b/DesktopEditor/doctrenderer/test/embed/external/Embed.h similarity index 94% rename from DesktopEditor/doctrenderer/test/internal/Embed.h rename to DesktopEditor/doctrenderer/test/embed/external/Embed.h index 80f06776a7..2d67bf898a 100644 --- a/DesktopEditor/doctrenderer/test/internal/Embed.h +++ b/DesktopEditor/doctrenderer/test/embed/external/Embed.h @@ -1,7 +1,7 @@ #ifndef _BUILD_NATIVE_HASH_EMBED_H_ #define _BUILD_NATIVE_HASH_EMBED_H_ -#include "../../js_internal/js_base.h" +#include "js_internal/js_base.h" #define ENABLE_SUM_DEL #define ENABLE_GET diff --git a/DesktopEditor/doctrenderer/test/internal/jsc/jsc_Embed.mm b/DesktopEditor/doctrenderer/test/embed/external/jsc/jsc_Embed.mm similarity index 100% rename from DesktopEditor/doctrenderer/test/internal/jsc/jsc_Embed.mm rename to DesktopEditor/doctrenderer/test/embed/external/jsc/jsc_Embed.mm diff --git a/DesktopEditor/doctrenderer/test/internal/main.cpp b/DesktopEditor/doctrenderer/test/embed/external/main.cpp similarity index 100% rename from DesktopEditor/doctrenderer/test/internal/main.cpp rename to DesktopEditor/doctrenderer/test/embed/external/main.cpp diff --git a/DesktopEditor/doctrenderer/test/internal/test_internal.pro b/DesktopEditor/doctrenderer/test/embed/external/test.pro similarity index 86% rename from DesktopEditor/doctrenderer/test/internal/test_internal.pro rename to DesktopEditor/doctrenderer/test/embed/external/test.pro index aa25c41f1f..6d2b027065 100644 --- a/DesktopEditor/doctrenderer/test/internal/test_internal.pro +++ b/DesktopEditor/doctrenderer/test/embed/external/test.pro @@ -9,7 +9,7 @@ TEMPLATE = app CONFIG += core_static_link_libstd -CORE_ROOT_DIR = $$PWD/../../../../../core +CORE_ROOT_DIR = $$PWD/../../../../../../core PWD_ROOT_DIR = $$PWD include($$CORE_ROOT_DIR/Common/base.pri) @@ -18,7 +18,7 @@ include($$CORE_ROOT_DIR/DesktopEditor/doctrenderer/js_internal/js_base_embed.pri ############### destination path ############### DESTDIR = $$PWD/build ################################################ -INCLUDEPATH += ../.. +INCLUDEPATH += $$CORE_ROOT_DIR/DesktopEditor/doctrenderer DEFINES += CURR_DIR=\\\"$$PWD_ROOT_DIR\\\" diff --git a/DesktopEditor/doctrenderer/test/internal/v8/v8_Embed.cpp b/DesktopEditor/doctrenderer/test/embed/external/v8/v8_Embed.cpp similarity index 100% rename from DesktopEditor/doctrenderer/test/internal/v8/v8_Embed.cpp rename to DesktopEditor/doctrenderer/test/embed/external/v8/v8_Embed.cpp diff --git a/DesktopEditor/doctrenderer/test/embed/test.cpp b/DesktopEditor/doctrenderer/test/embed/internal/hash/main.cpp similarity index 100% rename from DesktopEditor/doctrenderer/test/embed/test.cpp rename to DesktopEditor/doctrenderer/test/embed/internal/hash/main.cpp diff --git a/DesktopEditor/doctrenderer/test/embed/internal/hash/test.pro b/DesktopEditor/doctrenderer/test/embed/internal/hash/test.pro new file mode 100644 index 0000000000..9f1ad28169 --- /dev/null +++ b/DesktopEditor/doctrenderer/test/embed/internal/hash/test.pro @@ -0,0 +1,32 @@ +QT -= core +QT -= gui + +TARGET = test +CONFIG += console +CONFIG -= app_bundle + +TEMPLATE = app + +CONFIG += core_static_link_libstd + +CORE_ROOT_DIR = $$PWD/../../../../../../../core +CORE_3DPARTY_DIR = $$CORE_ROOT_DIR/Common/3dParty +PWD_ROOT_DIR = $$PWD + +include($$CORE_ROOT_DIR/Common/base.pri) +include($$CORE_3DPARTY_DIR/googletest/googletest.pri) + +DESTDIR = $$PWD/build + +INCLUDEPATH += $$CORE_ROOT_DIR/DesktopEditor/doctrenderer + +ADD_DEPENDENCY(doctrenderer) + +core_linux { + LIBS += -Wl,-unresolved-symbols=ignore-in-shared-libs + LIBS += -ldl +} + +SOURCES += \ + main.cpp + diff --git a/DesktopEditor/doctrenderer/test/js_internal/main.cpp b/DesktopEditor/doctrenderer/test/js_internal/main.cpp new file mode 100644 index 0000000000..5ebc571c58 --- /dev/null +++ b/DesktopEditor/doctrenderer/test/js_internal/main.cpp @@ -0,0 +1,124 @@ +#include "gtest/gtest.h" + +#include "js_internal/js_base.h" + +#include + +using namespace NSJSBase; + +class CGetPropertyNamesTest : public testing::Test +{ +public: + void SetUp() override + { + // create and enter context + m_pContext = new CJSContext(); + m_pContext->Enter(); + } + + void TearDown() override + { + m_pContext->Exit(); + } + + std::vector getObjectProperties(const std::string& objLiteral) + { + JSSmart obj = m_pContext->runScript("(() => { return " + objLiteral + ";})();")->toObject(); + return obj->getPropertyNames(); + } + + // The order of properties of object in JS is not always the same as insertion order. + // So this function sorts and compares two vectors with property names. + bool compare(std::vector& lhs, std::vector& rhs) + { + std::sort(lhs.begin(), lhs.end()); + std::sort(rhs.begin(), rhs.end()); + return lhs == rhs; + } + + std::string printInfo(const std::string& info, const std::vector& names) + { + std::string ret = info; + ret += '['; + const int lenResult = names.size(); + for (int i = 0; i < lenResult; i++) + { + ret += "\"" + names[i] + "\""; + if (i < lenResult - 1) + ret += ','; + } + ret += "]\n"; + return ret; + } + +public: + JSSmart m_pContext; +}; + + +TEST_F(CGetPropertyNamesTest, normal_object) +{ + std::vector result = getObjectProperties("{number: 42, name: 'foo', arr: [1, 'abc', 2, 3], func() { return 'bar'; }}"); + std::vector expected = {"number", "name", "arr", "func"}; + EXPECT_TRUE(compare(result, expected)) << printInfo("Actual: ", result) << printInfo("Expected: ", expected); +} + +TEST_F(CGetPropertyNamesTest, empty_object) +{ + std::vector result = getObjectProperties("{}"); + std::vector expected = {}; + EXPECT_TRUE(compare(result, expected)) << printInfo("Actual: ", result) << printInfo("Expected: ", expected); +} + +TEST_F(CGetPropertyNamesTest, only_one_function_in_object) +{ + std::vector result = getObjectProperties("{add(a, b) { return a + b; }}"); + std::vector expected = {"add"}; + EXPECT_TRUE(compare(result, expected)) << printInfo("Actual: ", result) << printInfo("Expected: ", expected); +} + +TEST_F(CGetPropertyNamesTest, inner_object) +{ + std::vector result = getObjectProperties("{inner: {number: 42, name: 'foo'}}"); + std::vector expected = {"inner"}; + EXPECT_TRUE(compare(result, expected)) << printInfo("Actual: ", result) << printInfo("Expected: ", expected); +} + +TEST_F(CGetPropertyNamesTest, object_with_null_and_undefined_properties) +{ + std::vector result = getObjectProperties("{number: null, name: undefined, func() { return 'bar'; }}"); + std::vector expected = {"number", "func"}; + EXPECT_TRUE(compare(result, expected)) << printInfo("Actual: ", result) << printInfo("Expected: ", expected); +} + +TEST_F(CGetPropertyNamesTest, object_with_only_undefined_properties) +{ + std::vector result = getObjectProperties("{foo: undefined, bar: undefined}"); + std::vector expected = {}; + EXPECT_TRUE(compare(result, expected)) << printInfo("Actual: ", result) << printInfo("Expected: ", expected); +} + +TEST_F(CGetPropertyNamesTest, array_as_object) +{ + std::vector result = getObjectProperties("{0: 4, 1: 2, 2: undefined, 3: 'foo', 42: 'bar'}"); + std::vector expected = {"0", "1", "3", "42"}; + EXPECT_TRUE(compare(result, expected)) << printInfo("Actual: ", result) << printInfo("Expected: ", expected); +} + +TEST_F(CGetPropertyNamesTest, object_with_prototype) +{ + m_pContext->runScript( + "var personPrototype = { greet() { return 'Hello, world!'; } };" + "function Person(name) { this.name = name; }" + ); + + JSSmart obj = m_pContext->runScript("new Person('Foo');")->toObject(); + std::vector result1 = obj->getPropertyNames(); + std::vector expected1 = {"name"}; + EXPECT_TRUE(compare(result1, expected1)) << printInfo("Actual: ", result1) << printInfo("Expected: ", expected1); + + m_pContext->runScript("Person.prototype.greet = personPrototype.greet;"); + std::vector result2 = obj->getPropertyNames(); + std::vector expected2 = {"name", "greet"}; + EXPECT_TRUE(compare(result2, expected2)) << printInfo("Actual: ", result2) << printInfo("Expected: ", expected2); +} diff --git a/DesktopEditor/doctrenderer/test/embed/test_embed.pro b/DesktopEditor/doctrenderer/test/js_internal/test.pro similarity index 83% rename from DesktopEditor/doctrenderer/test/embed/test_embed.pro rename to DesktopEditor/doctrenderer/test/js_internal/test.pro index b088bd08b7..e8554bc81f 100644 --- a/DesktopEditor/doctrenderer/test/embed/test_embed.pro +++ b/DesktopEditor/doctrenderer/test/js_internal/test.pro @@ -1,32 +1,32 @@ -QT -= core -QT -= gui - -TARGET = test -CONFIG += console -CONFIG -= app_bundle - -TEMPLATE = app - -CONFIG += core_static_link_libstd - -CORE_ROOT_DIR = $$PWD/../../../../../core -CORE_3DPARTY_DIR = $$CORE_ROOT_DIR/Common/3dParty -PWD_ROOT_DIR = $$PWD - -include($$CORE_ROOT_DIR/Common/base.pri) -include($$CORE_3DPARTY_DIR/googletest/googletest.pri) - -DESTDIR = $$PWD/build - -INCLUDEPATH += ../.. - -ADD_DEPENDENCY(doctrenderer) - -core_linux { - LIBS += -Wl,-unresolved-symbols=ignore-in-shared-libs - LIBS += -ldl -} - -SOURCES += \ - test.cpp - +QT -= core +QT -= gui + +TARGET = test +CONFIG += console +CONFIG -= app_bundle + +TEMPLATE = app + +CONFIG += core_static_link_libstd + +CORE_ROOT_DIR = $$PWD/../../../../../core +CORE_3DPARTY_DIR = $$CORE_ROOT_DIR/Common/3dParty +PWD_ROOT_DIR = $$PWD + +include($$CORE_ROOT_DIR/Common/base.pri) +include($$CORE_3DPARTY_DIR/googletest/googletest.pri) + +DESTDIR = $$PWD/build + +INCLUDEPATH += $$CORE_ROOT_DIR/DesktopEditor/doctrenderer + +ADD_DEPENDENCY(doctrenderer) + +core_linux { + LIBS += -Wl,-unresolved-symbols=ignore-in-shared-libs + LIBS += -ldl +} + +SOURCES += \ + main.cpp + diff --git a/DesktopEditor/doctrenderer/test/json/main.cpp b/DesktopEditor/doctrenderer/test/json/main.cpp new file mode 100644 index 0000000000..30fb4eb1b4 --- /dev/null +++ b/DesktopEditor/doctrenderer/test/json/main.cpp @@ -0,0 +1,943 @@ +#include "json/serialization.h" + +#ifdef JSON_GOOGLE_TEST +#include "gtest/gtest.h" +#include +#else +#include +#endif + +using namespace NSJSBase; +using namespace NSJSON; + +#ifdef JSON_GOOGLE_TEST + +class CJSONTest : public testing::Test +{ +public: + void SetUp() override + { + // create and enter context + m_pContext = new CJSContext(); + m_pContext->Enter(); + } + + void TearDown() override + { + m_pContext->Exit(); + } + + bool compare(const CValue& value, JSSmart jsValue, bool makeExpects = true) + { + if (value.IsUndefined()) + { + if (makeExpects) + EXPECT_TRUE(jsValue->isUndefined()); + return jsValue->isUndefined(); + } + if (value.IsNull()) + { + if (makeExpects) + EXPECT_TRUE(jsValue->isNull()); + return jsValue->isNull(); + } + + if (value.IsArray()) + { + if (makeExpects) + EXPECT_TRUE(jsValue->isArray()); + if (!jsValue->isArray()) + return false; + + JSSmart jsArr = jsValue->toArray(); + const int len = value.GetCount(); + + if (makeExpects) + EXPECT_EQ(len, jsArr->getCount()); + if (len != jsArr->getCount()) + return false; + + for (int i = 0; i < len; i++) + { + if (!compare(value[i], jsArr->get(i), makeExpects)) + { + if (makeExpects) + ADD_FAILURE() << "Array values at index [" << i << "] are different!"; + return false; + } + } + } + else if (value.IsTypedArray()) + { + if (makeExpects) + EXPECT_TRUE(jsValue->isTypedArray()); + if (!jsValue->isTypedArray()) + return false; + + JSSmart jsTypedArr = jsValue->toTypedArray(); + + if (makeExpects) + EXPECT_EQ(value.GetCount(), jsTypedArr->getCount()); + if (value.GetCount() != jsTypedArr->getCount()) + return false; + + // compare pointers, not values + if (makeExpects) + EXPECT_EQ(value.GetData(), jsTypedArr->getData().Data); + if (value.GetData() != jsTypedArr->getData().Data) + return false; + } + else if (value.IsObject()) + { + if (makeExpects) + EXPECT_TRUE(jsValue->isObject()); + if (!jsValue->isObject()) + return false; + + JSSmart jsObj = jsValue->toObject(); + std::vector properties = value.GetPropertyNames(); + std::vector jsProperties = jsObj->getPropertyNames(); + + const int len = properties.size(); + if (makeExpects) + EXPECT_EQ(len, jsProperties.size()); + if (len != jsProperties.size()) + return false; + + // sort both vectors since the order of properties may vary in them + std::sort(properties.begin(), properties.end()); + std::sort(jsProperties.begin(), jsProperties.end()); + + for (int i = 0; i < len; i++) + { + if (makeExpects) + EXPECT_EQ(properties[i], jsProperties[i]); + if (properties[i] != jsProperties[i]) + return false; + + const char* sProperty = properties[i].c_str(); + if (!compare(value[sProperty], jsObj->get(sProperty), makeExpects)) + { + if (makeExpects) + ADD_FAILURE() << "Object property values for property \"" << sProperty << "\" are different!"; + return false; + } + } + } + else + { + // primitive types + if (value.IsBool()) + { + if (makeExpects) + EXPECT_TRUE(jsValue->isBool()); + if (!jsValue->isBool()) + return false; + + bool val = (bool)value; + bool jsVal = jsValue->toBool(); + if (makeExpects) + EXPECT_EQ(val, jsVal); + if (val != jsVal) + return false; + } + else if (value.IsInt()) + { + if (makeExpects) + EXPECT_TRUE(jsValue->isNumber()); + if (!jsValue->isNumber()) + return false; + + int val = (int)value; + int jsVal = jsValue->toInt32(); + if (makeExpects) + EXPECT_EQ(val, jsVal); + if (val != jsVal) + return false; + } + else if (value.IsDouble()) + { + if (makeExpects) + EXPECT_TRUE(jsValue->isNumber()); + if (!jsValue->isNumber()) + return false; + + double val = (double)value; + double jsVal = jsValue->toDouble(); + if (!std::isnan(val)) + { + // strict check without tolerance + if (makeExpects) + EXPECT_EQ(val, jsVal); + if (val != jsVal) + return false; + } + else + { + if (makeExpects) + EXPECT_TRUE(std::isnan(jsVal)); + if (!std::isnan(jsVal)) + return false; + } + } + else if (value.IsStringA()) + { + if (makeExpects) + EXPECT_TRUE(jsValue->isString()); + if (!jsValue->isString()) + return false; + + std::string val = value.ToStringA(); + std::string jsVal = jsValue->toStringA(); + if (makeExpects) + EXPECT_EQ(val, jsVal); + if (val != jsVal) + return false; + } + else + { + if (makeExpects) + { + EXPECT_TRUE(value.IsStringW()); + EXPECT_TRUE(jsValue->isString()); + } + if (!jsValue->isString()) + return false; + + std::wstring val = value.ToStringW(); + std::wstring jsVal = jsValue->toStringW(); + if (makeExpects) + EXPECT_EQ(val, jsVal); + if (val != jsVal) + return false; + } + } + + return true; + } + +public: + JSSmart m_pContext; +}; + +// --------- CValue basic functinality tests ---------- + +TEST_F(CJSONTest, undefined_from_default_constructor) +{ + CValue val; + JSSmart jsVal = CJSContext::createUndefined(); + EXPECT_TRUE(compare(val, jsVal)); + val = 0; + EXPECT_FALSE(compare(val, jsVal, false)); +} + +TEST_F(CJSONTest, undefined_from_static_method) +{ + CValue val = CValue::CreateUndefined(); + JSSmart jsVal = CJSContext::createUndefined(); + EXPECT_TRUE(compare(val, jsVal)); + val = 5; + EXPECT_FALSE(compare(val, jsVal, false)); +} + +TEST_F(CJSONTest, null_) +{ + CValue val = CValue::CreateNull(); + JSSmart jsVal = CJSContext::createNull(); + EXPECT_TRUE(compare(val, jsVal)); + val = CValue(); + EXPECT_FALSE(compare(val, jsVal, false)); +} + +TEST_F(CJSONTest, bool_) +{ + CValue val = true; + JSSmart jsVal = CJSContext::createBool(true); + EXPECT_TRUE(compare(val, jsVal)); + val = false; + EXPECT_FALSE(compare(val, jsVal, false)); +} + +TEST_F(CJSONTest, int_) +{ + CValue val = 42; + EXPECT_FALSE(val.IsDouble()); + JSSmart jsVal = CJSContext::createInt(42); + EXPECT_TRUE(compare(val, jsVal)); + val = 100; + EXPECT_FALSE(compare(val, jsVal, false)); + val = 3; + jsVal = CJSContext::createDouble(3.0); + EXPECT_TRUE(compare(val, jsVal)); +} + +TEST_F(CJSONTest, double_) +{ + CValue val = 3.141592; + EXPECT_FALSE(val.IsInt()); + JSSmart jsVal = CJSContext::createDouble(3.141592); + EXPECT_TRUE(compare(val, jsVal)); + val = 2.81828; + jsVal = CJSContext::createDouble(3.0); + EXPECT_FALSE(compare(val, jsVal, false)); + val = 3.0; + jsVal = CJSContext::createInt(3); + EXPECT_TRUE(compare(val, jsVal)); +} + +TEST_F(CJSONTest, string_char_constructor) +{ + CValue val = "test"; + JSSmart jsVal = CJSContext::createString("test"); + EXPECT_TRUE(compare(val, jsVal)); + jsVal = CJSContext::createString(L"test"); + EXPECT_TRUE(compare(val, jsVal)); + val = ""; + EXPECT_FALSE(compare(val, jsVal, false)); +} + +TEST_F(CJSONTest, string_string_constructor) +{ + CValue val = std::string("test"); + JSSmart jsVal = CJSContext::createString("test"); + EXPECT_TRUE(compare(val, jsVal)); + jsVal = CJSContext::createString(L"test"); + EXPECT_TRUE(compare(val, jsVal)); + val = ""; + EXPECT_FALSE(compare(val, jsVal, false)); +} + +TEST_F(CJSONTest, wstring_wchar_constructor) +{ + CValue val = L"тест"; + JSSmart jsVal = CJSContext::createString(L"тест"); + EXPECT_TRUE(compare(val, jsVal)); + val = "test"; + EXPECT_FALSE(compare(val, jsVal, false)); + jsVal = CJSContext::createString(L"test"); + EXPECT_TRUE(compare(val, jsVal)); +} + +TEST_F(CJSONTest, wstring_wstring_constructor) +{ + CValue val = std::wstring(L"тест"); + JSSmart jsVal = CJSContext::createString(L"тест"); + EXPECT_TRUE(compare(val, jsVal)); + val = "test"; + EXPECT_FALSE(compare(val, jsVal, false)); + jsVal = CJSContext::createString(L"test"); + EXPECT_TRUE(compare(val, jsVal)); +} + +TEST_F(CJSONTest, array_from_static_method) +{ + CValue arr = CValue::CreateArray(4); + arr[0] = CValue::CreateNull(); + arr[1] = 42; + arr[2] = CValue::CreateArray(2); + arr[2][0] = true; + arr[2][1] = 2.5; + EXPECT_TRUE(arr[3].IsUndefined()); + EXPECT_TRUE(arr[100].IsUndefined()); + EXPECT_TRUE(arr[-1].IsUndefined()); + arr[5] = 1; + JSSmart jsArr = CJSContext::createArray(4); + jsArr->set(0, CJSContext::createNull()); + jsArr->set(1, CJSContext::createInt(42)); + jsArr->set(2, CJSContext::createArray(2)); + jsArr->get(2)->toArray()->set(0, CJSContext::createBool(true)); + jsArr->get(2)->toArray()->set(1, CJSContext::createDouble(2.5)); + jsArr->set(3, CJSContext::createUndefined()); + EXPECT_TRUE(compare(arr, jsArr->toValue())); + arr[1] = 41; + EXPECT_FALSE(compare(arr, jsArr->toValue(), false)); +} + +TEST_F(CJSONTest, array_from_initializer_list) +{ + CValue arr = {CValue::CreateNull(), 42, {true, 2.5}, CValue::CreateUndefined()}; + EXPECT_TRUE(arr[3].IsUndefined()); + EXPECT_TRUE(arr[100].IsUndefined()); + EXPECT_TRUE(arr[-1].IsUndefined()); + arr[5] = 1; + JSSmart jsArr = CJSContext::createArray(4); + jsArr->set(0, CJSContext::createNull()); + jsArr->set(1, CJSContext::createInt(42)); + jsArr->set(2, CJSContext::createArray(2)); + jsArr->get(2)->toArray()->set(0, CJSContext::createBool(true)); + jsArr->get(2)->toArray()->set(1, CJSContext::createDouble(2.5)); + jsArr->set(3, CJSContext::createUndefined()); + EXPECT_TRUE(compare(arr, jsArr->toValue())); + arr[1] = 41; + EXPECT_FALSE(compare(arr, jsArr->toValue(), false)); +} + +TEST_F(CJSONTest, array_empty) +{ + CValue arr = CValue::CreateArray(0); + EXPECT_TRUE(arr.IsArray()); + EXPECT_EQ(arr.GetCount(), 0); + EXPECT_TRUE(arr[0].IsUndefined()); +} + +TEST_F(CJSONTest, array_negative_size) +{ + CValue arr = CValue::CreateArray(-1); + EXPECT_TRUE(arr.IsUndefined()); + EXPECT_TRUE(arr[100].IsUndefined()); +} + +TEST_F(CJSONTest, typed_array_externalize) +{ + BYTE* data = CValue::AllocTypedArray(10); + CValue typedArr = CValue::CreateTypedArray(data, 10); + JSSmart jsTypedArr = CJSContext::createUint8Array(data, 10); + EXPECT_TRUE(compare(typedArr, jsTypedArr->toValue())); + typedArr = CValue::CreateTypedArray(data, 11); + EXPECT_FALSE(compare(typedArr, jsTypedArr->toValue(), false)); + BYTE* data2 = CValue::AllocTypedArray(10); + typedArr = CValue::CreateTypedArray(data2, 10); + EXPECT_FALSE(compare(typedArr, jsTypedArr->toValue(), false)); + + CValue::FreeTypedArray(data, 10); + CValue::FreeTypedArray(data2, 10); +} + +TEST_F(CJSONTest, typed_array_not_externalize) +{ + BYTE* data = CValue::AllocTypedArray(10); + CValue typedArr = CValue::CreateTypedArray(data, 10, false); + JSSmart jsTypedArr = CJSContext::createUint8Array(data, 10); + EXPECT_TRUE(compare(typedArr, jsTypedArr->toValue())); +} + +TEST_F(CJSONTest, typed_array_empty) +{ + BYTE* data = CValue::AllocTypedArray(0); + CValue typedArr = CValue::CreateTypedArray(data, 0, false); + EXPECT_TRUE(typedArr.IsUndefined()); +} + +TEST_F(CJSONTest, typed_array_negative_size) +{ + BYTE* data = CValue::AllocTypedArray(10); + CValue typedArr = CValue::CreateTypedArray(nullptr, -10); + EXPECT_TRUE(typedArr.IsUndefined()); + CValue::FreeTypedArray(data, 10); +} + +TEST_F(CJSONTest, typed_array_copy) +{ + BYTE* data = CValue::AllocTypedArray(10); + CValue typedArr = CValue::CreateTypedArray(data, 10, false); + { + CValue typedArr2 = typedArr; + typedArr2.GetData()[4] = 0x42; + } + EXPECT_EQ(typedArr.GetData()[4], 0x42); +} + +TEST_F(CJSONTest, object) +{ + CValue obj = CValue::CreateObject(); + JSSmart jsObj = CJSContext::createObject(); + EXPECT_TRUE(compare(obj, jsObj->toValue())); + obj["name"] = "Foo"; + jsObj->set("name", CJSContext::createString("Foo")); + EXPECT_TRUE(compare(obj, jsObj->toValue())); + obj["name"] = "Bar"; + EXPECT_FALSE(compare(obj, jsObj->toValue(), false)); + obj["number"] = 42; + jsObj->set("name", CJSContext::createString("Bar")); + jsObj->set("number", CJSContext::createInt(42)); + EXPECT_TRUE(compare(obj, jsObj->toValue())); + obj["extra"] = CValue::CreateUndefined(); + EXPECT_TRUE(compare(obj, jsObj->toValue())); + obj["extra"] = CValue::CreateNull(); + EXPECT_FALSE(compare(obj, jsObj->toValue(), false)); +} + +TEST_F(CJSONTest, references) +{ + CValue val = 42; + CValueRef ref = val; + EXPECT_EQ((int)val, 42); + EXPECT_EQ((int)ref, 42); + ref = 10; + EXPECT_EQ((int)val, 10); + EXPECT_EQ((int)ref, 10); + // CValue from CValueRef + CValue val2 = ref; + val2 = 12; + EXPECT_EQ((int)val2, 12); + EXPECT_EQ((int)ref, 10); + EXPECT_EQ((int)val, 10); + // chaining CValueRef-s + CValueRef ref2 = ref; + val = "foo"; + EXPECT_EQ((std::string)ref, "foo"); + EXPECT_EQ((std::string)ref2, "foo"); + val = {1, 2, 3}; + EXPECT_EQ((int)ref[1], 2); + // CValue assignment to CValueRef + val2 = ref2; + EXPECT_EQ((int)val2[0], 1); + val2 = true; + EXPECT_EQ((bool)val2, true); + EXPECT_TRUE(ref.IsArray()); + EXPECT_TRUE(ref2.IsArray()); + // CValueRef from operator[] + CValueRef ref3 = val[2]; + ref3 = ref2[0]; + EXPECT_EQ((int)val[2], 1); +} + +TEST_F(CJSONTest, constants) +{ + const CValue val = 42; + // NOTE: you can't change constant value explicitly, but you can do it using references: + CValueRef ref = val; + ref = 10; + EXPECT_EQ((int)val, 10); + EXPECT_EQ((int)ref, 10); + // NOTE: const references saves its const properties + const CValueRef ref2 = ref; + // you can't do that: +// ref2 = 100; + EXPECT_EQ((int)ref2, 10); +} + +TEST_F(CJSONTest, wrong_usage) +{ + CValue val = 42; + EXPECT_TRUE(val["name"].IsUndefined()); + EXPECT_TRUE(val[0].IsUndefined()); + EXPECT_TRUE(val.GetPropertyNames().empty()); + EXPECT_EQ(val.GetCount(), 0); + EXPECT_EQ(val.GetData(), nullptr); + EXPECT_DOUBLE_EQ(val.ToDouble(), 42.0); +#ifdef JSON_DEBUG + EXPECT_THROW((bool)val, std::bad_cast); + EXPECT_THROW((std::string)val, std::bad_cast); + EXPECT_THROW((std::wstring)val, std::bad_cast); +#else + EXPECT_EQ((bool)val, false); + EXPECT_EQ((std::string)val, ""); + EXPECT_EQ((std::wstring)val, L""); +#endif + + val = 3.1415926535; + EXPECT_EQ((int)val, 3); + + val = "test"; +#ifdef JSON_DEBUG + EXPECT_THROW((bool)val, std::bad_cast); + EXPECT_THROW((int)val, std::bad_cast); + EXPECT_THROW((double)val, std::bad_cast); + EXPECT_THROW((std::wstring)val, std::bad_cast); +#else + EXPECT_EQ((bool)val, false); + EXPECT_EQ((int)val, 0); + EXPECT_EQ((double)val, 0.0); + EXPECT_EQ((std::wstring)val, L""); +#endif + + val = L"тест"; +#ifdef JSON_DEBUG + EXPECT_THROW((bool)val, std::bad_cast); + EXPECT_THROW((int)val, std::bad_cast); + EXPECT_THROW((double)val, std::bad_cast); + EXPECT_THROW((std::string)val, std::bad_cast); +#else + EXPECT_EQ((bool)val, false); + EXPECT_EQ((int)val, 0); + EXPECT_EQ((double)val, 0.0); + EXPECT_EQ((std::string)val, ""); +#endif + + val = CValue::CreateObject(); +#ifdef JSON_DEBUG + EXPECT_THROW((bool)val, std::bad_cast); + EXPECT_THROW((int)val, std::bad_cast); + EXPECT_THROW((double)val, std::bad_cast); + EXPECT_THROW((std::string)val, std::bad_cast); + EXPECT_THROW((std::wstring)val, std::bad_cast); +#else + EXPECT_EQ((bool)val, false); + EXPECT_EQ((int)val, 0); + EXPECT_EQ((double)val, 0.0); + EXPECT_EQ((std::string)val, ""); + EXPECT_EQ((std::wstring)val, L""); +#endif +} + +// ----------- toJS() tests ----------- + +TEST_F(CJSONTest, toJS_undefined) +{ + CValue val; + JSSmart jsVal = toJS(val); + EXPECT_TRUE(compare(val, jsVal)); +} + +TEST_F(CJSONTest, toJS_null) +{ + CValue val = CValue::CreateNull(); + JSSmart jsVal = toJS(val); + EXPECT_TRUE(compare(val, jsVal)); +} + +TEST_F(CJSONTest, toJS_typed_arrays) +{ + BYTE* data = CValue::AllocTypedArray(4); + data[0] = 0x1A; + data[1] = 0x54; + data[2] = 0xFE; + data[3] = 0xFF; + CValue typedArr = CValue::CreateTypedArray(data, 4, false); + JSSmart jsTypedArr = toJS(typedArr); + // NOTE: BE CAREFUL WHEN CALLLING toJS() MULTIPLE TIMES WITH THE SAME TYPED ARRAY! + // second typed array will NOT be initialized properly, since there is another `CJSTypedArray` containing this memory! +// JSSmart jsTypedArr2 = toJS(typedArr); + EXPECT_TRUE(compare(typedArr, jsTypedArr)); +} + +TEST_F(CJSONTest, toJS_arrays) +{ + BYTE* data = CValue::AllocTypedArray(4); + data[0] = 0x1A; + data[1] = 0x54; + data[2] = 0xFE; + data[3] = 0xFF; + CValue typedArr = CValue::CreateTypedArray(data, 4, false); + + // can't add typed array to this inner array (see test above), only to external array + CValue arrInner = {true, 42, L"тест функции toJS()", 2.71828, CValue(), "abc de f", L"test"}; + CValue arr = {0, arrInner, arrInner, CValue::CreateNull(), arrInner, CValue::CreateArray(4), typedArr}; + + JSSmart jsArr = toJS(arr); + EXPECT_TRUE(compare(arr, jsArr)); +} + +TEST_F(CJSONTest, toJS_arrays_circular) +{ + // NOTE: BE CAREFULL WHEN CREATING CIRCULAR REFERENCE DEPENDENCY IN YOUR ARRAY OR OBJECT! + CValue arr = CValue::CreateArray(2); + CValueRef ref = arr; + arr[0] = 3; + arr[1] = ref; + // or simply: +// arr[1] = arr; + + EXPECT_EQ((int)arr[0], 3); + EXPECT_EQ((int)arr[1][0], 3); + EXPECT_EQ((int)arr[1][1][1][1][1][1][1][1][1][1][0], 3); + EXPECT_TRUE(arr[1][1][1][1].IsArray()); + // here you will get stack overflow, because each inner array reference will be transformed to a new copy of `CJSArray` +// JSSmart jsArr = toJS(arr); + + // keep only 2 inner recursions + CValue arrRec = arr[1][1]; + arrRec[1] = 42; + EXPECT_TRUE(arr[1].IsInt()); + + JSSmart jsArr = toJS(arr); + EXPECT_TRUE(compare(arr, jsArr)); +} + +TEST_F(CJSONTest, toJS_objects) +{ + CValue obj = CValue::CreateObject(); + obj["name"] = L"Foo"; + obj["parameters"] = CValue::CreateObject(); + CValueRef parameters = obj["parameters"]; + parameters["size"] = 42; + parameters["arr"] = {CValue::CreateNull(), CValue::CreateArray(0), {42, L"тест функции toJS()", 2.71828}, CValue::CreateObject(), CValue(), "abc de f", L"test"}; + parameters["0"] = 0; + + BYTE* data = CValue::AllocTypedArray(4); + data[0] = 0x1A; + data[1] = 0x54; + data[2] = 0xFE; + data[3] = 0xFF; + CValue typedArr = CValue::CreateTypedArray(data, 4, false); + obj["typed"] = typedArr; + // NOTE: you can create property even without a name (like in JS) + obj[""] = "Bar"; + + JSSmart jsObj = toJS(obj); + EXPECT_TRUE(compare(obj, jsObj)); +} + +// ----------- fromJS() tests ----------- + +TEST_F(CJSONTest, fromJS_undefined) +{ + JSSmart jsVal = CJSContext::createUndefined(); + CValue val = fromJS(jsVal); + EXPECT_TRUE(compare(val, jsVal)); +} + +TEST_F(CJSONTest, fromJS_null) +{ + JSSmart jsVal = CJSContext::createNull(); + CValue val = fromJS(jsVal); + EXPECT_TRUE(compare(val, jsVal)); +} + +TEST_F(CJSONTest, fromJS_and_toJS_edge_numbers) +{ + JSSmart jsVal = CJSContext::createArray(16); + jsVal->set(0, INT_MIN); + jsVal->set(1, INT_MAX); + jsVal->set(2, 0); + jsVal->set(3, 42); + jsVal->set(4, 0.0); + jsVal->set(5, 3.1415926535); + jsVal->set(6, 42.0); + jsVal->set(7, (double)INT_MIN); + jsVal->set(8, (double)INT_MAX); + jsVal->set(9, std::pow(2.0, 31) - 1); + jsVal->set(10, std::pow(2.0, 31)); + jsVal->set(11, -std::pow(2.0, 31)); + jsVal->set(12, -std::pow(2.0, 31) - 1); + jsVal->set(13, INFINITY); + jsVal->set(14, NAN); + jsVal->set(15, -INFINITY); + + CValue val = fromJS(jsVal->toValue()); + EXPECT_TRUE(compare(val, jsVal->toValue())); + EXPECT_TRUE(val[0].IsInt()); // INT_MIN + EXPECT_TRUE(val[1].IsInt()); // INT_MAX + EXPECT_TRUE(val[2].IsInt()); // 0 + EXPECT_TRUE(val[3].IsInt()); // 42 + EXPECT_TRUE(val[4].IsInt()); // 0.0 + EXPECT_TRUE(val[5].IsDouble()); // 3.1415926535 + EXPECT_TRUE(val[6].IsInt()); // 42.0 + EXPECT_TRUE(val[7].IsInt()); // (double)INT_MIN + EXPECT_TRUE(val[8].IsInt()); // (double)INT_MAX + EXPECT_TRUE(val[9].IsInt()); // 2^31 - 1 == INT_MAX + EXPECT_TRUE(val[10].IsDouble()); // 2^31 + EXPECT_TRUE(val[11].IsInt()); // -2^31 == INT_MIN + EXPECT_TRUE(val[12].IsDouble()); // -2^31 - 1 + EXPECT_TRUE(val[13].IsDouble()); // inf + EXPECT_TRUE(val[14].IsDouble()); // NaN + EXPECT_TRUE(val[15].IsDouble()); // -inf + + JSSmart jsVal2 = toJS(val); + EXPECT_TRUE(compare(val, jsVal2)); +} + +TEST_F(CJSONTest, fromJS_typed_arrays) +{ + BYTE* data = NSAllocator::Alloc(4); + data[0] = 0x1A; + data[1] = 0x54; + data[2] = 0xFE; + data[3] = 0xFF; + JSSmart jsTypedArr = CJSContext::createUint8Array(data, 4, false); + CValue typedArr = fromJS(jsTypedArr); + EXPECT_TRUE(compare(typedArr, jsTypedArr)); +} + +TEST_F(CJSONTest, fromJS_arrays) +{ + BYTE* data = NSAllocator::Alloc(4); + data[0] = 0x1A; + data[1] = 0x54; + data[2] = 0xFE; + data[3] = 0xFF; + JSSmart jsTypedArr = CJSContext::createUint8Array(data, 4, false); + JSSmart jsArrInner = CJSContext::createArray(0); + jsArrInner->add_bool(true); + jsArrInner->add_int(42); + jsArrInner->add_string(L"тест функции fromJS()"); + jsArrInner->add_double(2.71828); + jsArrInner->add_undefined(); + jsArrInner->add_stringa("abc de f"); + jsArrInner->add_string(L"test"); + JSSmart jsArr = CJSContext::createArray(0); + jsArr->add_int(0); + jsArr->add(jsArrInner->toValue()); + jsArr->add(jsArrInner->toValue()); + jsArr->add_null(); + jsArr->add(jsArrInner->toValue()); + jsArr->add(CJSContext::createArray(4)); + jsArr->add(jsTypedArr); + + CValue arr = fromJS(jsArr->toValue()); + EXPECT_TRUE(compare(arr, jsArr->toValue())); +} + +TEST_F(CJSONTest, fromJS_objects) +{ + JSSmart jsObj = CJSContext::createObject(); + jsObj->set("name", CJSContext::createString(L"Foo")); + + JSSmart jsParam = CJSContext::createObject(); + jsParam->set("size", 42); + jsParam->set("arr", CJSContext::createArray(0)); + + JSSmart jsArr = jsParam->get("arr")->toArray(); + jsArr->add_null(); + jsArr->add(CJSContext::createArray(0)); + jsArr->add(CJSContext::createArray(3)); + jsArr->get(2)->toArray()->set(0, 42); + jsArr->get(2)->toArray()->set(1, CJSContext::createString(L"тест функции fromJS()")); + jsArr->get(2)->toArray()->set(2, 2.71828); + jsArr->add(CJSContext::createObject()); + jsArr->add_undefined(); + jsArr->add_stringa("abc de f"); + jsArr->add_bool(true); + jsParam->set("0", 0); + + jsObj->set("parameters", jsParam); + + BYTE* data = NSAllocator::Alloc(4); + data[0] = 0x1A; + data[1] = 0x54; + data[2] = 0xFE; + data[3] = 0xFF; + JSSmart jsTypedArr = CJSContext::createUint8Array(data, 4, false); + + jsObj->set("typed", jsTypedArr); + jsObj->set("", CJSContext::createString("Bar")); + + CValue obj = fromJS(jsObj->toValue()); + EXPECT_TRUE(compare(obj, jsObj->toValue())); +} + +TEST_F(CJSONTest, serialization_with_script) +{ + JSSmart jsObj = m_pContext->runScript( + "(() => {" + " let obj = {};" + " obj['name'] = 'Foo';" + " obj['parameters'] = { size: 42, arr: [null, [], [42, 'test', 2.71828], {}, undefined, 'abc de f', ''], 0: 0, typedArr: { data: null, count: 0 } };" + " obj[''] = 'Bar';" + " return obj;" + "})();" + ); + + CValue obj = fromJS(jsObj); + + EXPECT_EQ(obj["name"].ToStringW(), L"Foo"); + EXPECT_EQ(obj[""].ToStringW(), L"Bar"); + EXPECT_EQ((double)obj["parameters"]["arr"][2][0], 42); + EXPECT_TRUE(obj["parameters"]["arr"][4].IsUndefined()); + EXPECT_EQ((int)obj["parameters"]["0"], 0); + EXPECT_TRUE(obj["parameters"]["typedArr"]["data"].IsNull()); + + EXPECT_TRUE(compare(obj, jsObj)); + + // function test() returns 0 if all checks have passed and number of failed check otherwise + m_pContext->runScript( + "function test(obj) {" + " if (obj['name'] !== 'Foo')" + " return 1;" + " if (obj[''] !== 'Bar')" + " return 2;" + " if (obj['parameters']['arr'][2][0] !== 42)" + " return 3;" + " if (obj['parameters']['arr'][4] !== undefined)" + " return 4;" + " if (obj['parameters']['0'] !== 0)" + " return 5;" + " if (obj['parameters']['typedArr']['data'] !== null)" + " return 6;" + " return 0;" + "}" + ); + + JSSmart global = m_pContext->GetGlobal(); + JSSmart args[1]; + args[0] = toJS(obj); + + JSSmart jsCheckResult = global->call_func("test", 1, args); + + EXPECT_TRUE(jsCheckResult->isNumber()); + EXPECT_EQ(jsCheckResult->toInt32(), 0); + + EXPECT_TRUE(compare(obj, args[0])); +} + +#else +int main() +{ + JSSmart pContext = new CJSContext(); + CJSContextScope scope(pContext); + + // top object with some text parameters + CValue textPr = CValue::CreateObject(); + + CValue colorRGB = CValue::CreateObject(); + colorRGB["r"] = 12; + colorRGB["g"] = 34; + colorRGB["b"] = 56; + + CValue colorRGBA = CValue::CreateObject(); + colorRGBA["rgb"] = colorRGB; + colorRGBA["alpha"] = 80; + + // CValueRef behaves as reference + CValueRef name = textPr["name"]; + // from now on, name - is a reference to the property "name" of textPr. Changing it will affect this object property: + name = "Foo"; + // Also you can chain references + CValueRef name3 = name; + name3 = "FooBar"; // this change applies to textPr["name"] + // The same but with CValue wouldnt' work: + CValue name2 = textPr["name"]; + name2 = "Bar"; // this change doesn't affect the property "name" of textPr + + textPr["size"] = 4.2; + textPr["color"] = colorRGBA; + textPr["font"] = CValue::CreateObject(); + textPr["font"]["fontName"] = L"Times New Roman"; + textPr["font"]["bold"] = true; + // undefined member: + textPr["font"]["italic"] = CValue::CreateUndefined(); + // or just +// textPr["font"]["italic"]; + // null member: + textPr["extras"] = CValue::CreateNull(); + // array + CValue numbers = {10000, 12, 42, 0, 147}; + // inner array + CValue innerArray = {true, "abc", 3.1415926535, L"ABC", 4}; + numbers[3] = innerArray; + textPr["numbers"] = numbers; + // create typed array + BYTE* pData = CValue::AllocTypedArray(4); + pData[0] = 11; + pData[1] = 23; + pData[2] = 58; + pData[3] = 13; + // add typed array + CValue typedArr = CValue::CreateTypedArray(pData, 4, false); + textPr["typedArr"] = typedArr; + + // convert to JS + JSSmart jsObj = toJS(textPr)->toObject(); + JSSmart global = pContext->GetGlobal(); + global->set("textPr", jsObj); + JSSmart ret = pContext->runScript("(function () { return JSON.stringify(textPr, null, 4); })();"); + if (ret.IsInit()) + { + std::cout << ret->toStringA() << std::endl; + } + + // convert fromJS() the same object: + CValue textPr2 = fromJS(jsObj->toValue()); + // and then back toJS() to see if result is the same + JSSmart jsObj2 = toJS(textPr2)->toObject(); + global->set("textPr2", jsObj2); + ret = pContext->runScript("(function () { return JSON.stringify(textPr2, null, 4); })();"); + if (ret.IsInit()) + { + std::cout << ret->toStringA() << std::endl; + } + + return 0; +} +#endif // JSON_GOOGLE_TEST diff --git a/DesktopEditor/doctrenderer/test/json/test.pro b/DesktopEditor/doctrenderer/test/json/test.pro new file mode 100644 index 0000000000..e6323902bf --- /dev/null +++ b/DesktopEditor/doctrenderer/test/json/test.pro @@ -0,0 +1,39 @@ +QT -= core +QT -= gui + +TARGET = test +CONFIG += console +CONFIG -= app_bundle + +TEMPLATE = app + +CONFIG += core_static_link_libstd + +CORE_ROOT_DIR = $$PWD/../../../../../core +CORE_3DPARTY_DIR = $$CORE_ROOT_DIR/Common/3dParty +PWD_ROOT_DIR = $$PWD + +include($$CORE_ROOT_DIR/Common/base.pri) + +# Comment to inspect simple usage example +# Uncomment to run google tests +CONFIG += json_google_test + +json_google_test { + include($$CORE_3DPARTY_DIR/googletest/googletest.pri) + DEFINES += JSON_GOOGLE_TEST +} + +DESTDIR = $$PWD/build + +INCLUDEPATH += ../.. + +ADD_DEPENDENCY(doctrenderer) + +core_linux { + LIBS += -Wl,-unresolved-symbols=ignore-in-shared-libs + LIBS += -ldl +} + +SOURCES += \ + main.cpp diff --git a/DesktopEditor/graphics/Graphics.cpp b/DesktopEditor/graphics/Graphics.cpp index 769310a6d6..8a83395f5b 100644 --- a/DesktopEditor/graphics/Graphics.cpp +++ b/DesktopEditor/graphics/Graphics.cpp @@ -105,7 +105,9 @@ namespace Aggplus #endif m_dDpiTile = -1; - + + m_pAlphaMask = NULL; + m_nTextRenderMode = FT_RENDER_MODE_NORMAL; m_nBlendMode = agg::comp_op_src_over; @@ -146,7 +148,9 @@ namespace Aggplus #endif m_dDpiTile = -1; - + + m_pAlphaMask = NULL; + m_nTextRenderMode = FT_RENDER_MODE_NORMAL; m_nBlendMode = agg::comp_op_src_over; @@ -161,6 +165,12 @@ namespace Aggplus #endif RELEASEINTERFACE(m_pAlphaMask); + + while (!m_arLayers.empty()) + { + RELEASEINTERFACE(m_arLayers.top()); + m_arLayers.pop(); + } } INT CGraphics::IsDib() @@ -1242,6 +1252,105 @@ namespace Aggplus m_pAlphaMask->m_internal->StartApplying(); return Ok; } + + Status CGraphics::AddLayer(CGraphicsLayer *pGraphicsLayer) + { + if (NULL == pGraphicsLayer || pGraphicsLayer->Empty()) + return InvalidParameter; + + m_arLayers.push(pGraphicsLayer); + pGraphicsLayer->AddRef(); + + int nStride = m_frame_buffer.ren_buf().stride(); + const unsigned int unWidth = m_frame_buffer.ren_buf().width(); + const unsigned int unHeight = m_frame_buffer.ren_buf().height(); + + m_frame_buffer.create(unWidth, unHeight, false, nStride, pGraphicsLayer->GetBuffer()); + + return Ok; + } + + Status CGraphics::CreateLayer() + { + int nStride = m_frame_buffer.ren_buf().stride(); + const unsigned int unWidth = m_frame_buffer.ren_buf().width(); + const unsigned int unHeight = m_frame_buffer.ren_buf().height(); + + BYTE *pBuffer = new BYTE[unWidth * unHeight * m_frame_buffer.pix_size]; + + memset(pBuffer, 0x00, unWidth * unHeight * m_frame_buffer.pix_size); + + m_frame_buffer.create(unWidth, unHeight, false, nStride, pBuffer); + + m_arLayers.push(new CGraphicsLayer(pBuffer, false)); + return Ok; + } + + Status CGraphics::BlendLayer() + { + if (m_arLayers.empty()) + return WrongState; + + CGraphicsLayer *pCurrentGraphicsLayer = m_arLayers.top(); + m_arLayers.pop(); + + BYTE* pBuffer = NULL; + + if (!m_arLayers.empty()) + pBuffer = m_arLayers.top()->GetBuffer(); + else + pBuffer = m_pPixels; + + if (NULL == pBuffer) + { + RELEASEINTERFACE(pCurrentGraphicsLayer); + return WrongState; + } + + agg::rendering_buffer *pRenBuffer = &GetRenderingBuffer(); + + pRenBuffer->attach(pBuffer, m_frame_buffer.ren_buf().width(), m_frame_buffer.ren_buf().height(), pRenBuffer->stride()); + + pCurrentGraphicsLayer->BlendTo(m_frame_buffer.pixfmt()); + + RELEASEINTERFACE(pCurrentGraphicsLayer); + return Ok; + } + + Status CGraphics::RemoveLayer() + { + if (m_arLayers.empty()) + return WrongState; + + CGraphicsLayer *pCurrentGraphicsLayer = m_arLayers.top(); + m_arLayers.pop(); + + RELEASEINTERFACE(pCurrentGraphicsLayer); + return Ok; + } + + Status CGraphics::SetLayerSettings(const TGraphicsLayerSettings &oSettings) + { + if (m_arLayers.empty()) + return WrongState; + + m_arLayers.top()->SetSettings(oSettings); + + return Ok; + } + + Status CGraphics::SetLayerOpacity(double dOpacity) + { + if (dOpacity < 0. || dOpacity > 1.) + return InvalidParameter; + + if (m_arLayers.empty()) + return WrongState; + + m_arLayers.top()->SetOpacity(dOpacity); + + return Ok; + } void CGraphics::CalculateFullTransform() { diff --git a/DesktopEditor/graphics/Graphics.h b/DesktopEditor/graphics/Graphics.h index 8895dbfa2a..87f0969477 100644 --- a/DesktopEditor/graphics/Graphics.h +++ b/DesktopEditor/graphics/Graphics.h @@ -64,6 +64,7 @@ #include "Color.h" #include "Matrix.h" +#include "GraphicsLayer.h" #include "GraphicsPath.h" #include "AlphaMask.h" #include "Clip.h" @@ -71,6 +72,7 @@ #include "Image.h" #include "../fontengine/FontManager.h" +#include #include #if defined(_WIN32) || defined (_WIN64) @@ -281,6 +283,8 @@ protected: CAlphaMask* m_pAlphaMask; + std::stack m_arLayers; + agg::svg::frame_buffer_rgba m_frame_buffer; agg::svg::rasterizer m_rasterizer; @@ -402,6 +406,15 @@ public: Status ResetAlphaMask(); Status StartApplyingAlphaMask(); + //Работа со слоями + Status AddLayer(CGraphicsLayer* pGraphicsLayer); + Status CreateLayer(); + Status BlendLayer(); + Status RemoveLayer(); + + Status SetLayerSettings(const TGraphicsLayerSettings& oSettings); + Status SetLayerOpacity(double dOpacity); + void CalculateFullTransform(); bool IsClip(); diff --git a/DesktopEditor/graphics/GraphicsLayer.cpp b/DesktopEditor/graphics/GraphicsLayer.cpp new file mode 100644 index 0000000000..5c223f41e4 --- /dev/null +++ b/DesktopEditor/graphics/GraphicsLayer.cpp @@ -0,0 +1,50 @@ +#include "GraphicsLayer.h" + +namespace Aggplus +{ + CGraphicsLayer::CGraphicsLayer(BYTE *pBuffer, bool bExternalBuffer) + : m_pBuffer(pBuffer), m_bExternalBuffer(NULL != pBuffer && bExternalBuffer) + { + SetDefaultSettings(); + } + + CGraphicsLayer::~CGraphicsLayer() + { + if (!m_bExternalBuffer) + RELEASEARRAYOBJECTS(m_pBuffer); + } + + bool CGraphicsLayer::Empty() const + { + return NULL == m_pBuffer; + } + + BYTE *CGraphicsLayer::GetBuffer() + { + return m_pBuffer; + } + + void CGraphicsLayer::SetDefaultSettings() + { + m_oSettings.m_dOpacity = 1.; + } + + void CGraphicsLayer::SetSettings(const TGraphicsLayerSettings &oSettings) + { + m_oSettings = oSettings; + } + + const TGraphicsLayerSettings &CGraphicsLayer::GetSettings() const + { + return m_oSettings; + } + + void CGraphicsLayer::SetOpacity(double dOpacity) + { + if (dOpacity > 1. || dOpacity < 0.) + m_oSettings.m_dOpacity = 1.; + else + m_oSettings.m_dOpacity = dOpacity; + } +} + diff --git a/DesktopEditor/graphics/GraphicsLayer.h b/DesktopEditor/graphics/GraphicsLayer.h new file mode 100644 index 0000000000..e26838018a --- /dev/null +++ b/DesktopEditor/graphics/GraphicsLayer.h @@ -0,0 +1,83 @@ +#ifndef CGRAPHICSLAYER_H +#define CGRAPHICSLAYER_H + +#include "Defines.h" +#include "./config.h" +#include "../common/IGrObject.h" + +namespace Aggplus +{ + struct TGraphicsLayerSettings + { + double m_dOpacity; + }; + + class GRAPHICS_DECL CGraphicsLayer : public IGrObject + { + public: + CGraphicsLayer(BYTE* pBuffer, bool bExternalBuffer = true); + ~CGraphicsLayer(); + + bool Empty() const; + BYTE* GetBuffer(); + + void SetDefaultSettings(); + + void SetSettings(const TGraphicsLayerSettings& oSettings); + const TGraphicsLayerSettings& GetSettings() const; + + void SetOpacity(double dOpacity); + + template + void BlendTo(SrcPixelFormatRenderer& oSrc) + { + if (NULL == m_pBuffer) + return; + + typedef typename SrcPixelFormatRenderer::order_type order_type; + typedef typename SrcPixelFormatRenderer::value_type value_type; + + int nStep = 4; + BYTE* pSrcBuffer = m_pBuffer; + value_type* pDstBuffer = NULL; + BYTE uchAlpha; + + unsigned int unSrcW = oSrc.width(); + unsigned int unSrcH = oSrc.height(); + + for (unsigned int unY = 0; unY < unSrcH; ++unY) + { + pDstBuffer = oSrc.row_ptr(unY); + for (unsigned int unX = 0; unX < unSrcW; ++unX) + { + uchAlpha = (pSrcBuffer[order_type::A] * ((value_type)(m_oSettings.m_dOpacity * 255.)) + 1) >> 8; + if (uchAlpha) + { + if(uchAlpha == SrcPixelFormatRenderer::base_mask) + { + pDstBuffer[order_type::R] = pSrcBuffer[order_type::R]; + pDstBuffer[order_type::G] = pSrcBuffer[order_type::G]; + pDstBuffer[order_type::B] = pSrcBuffer[order_type::B]; + pDstBuffer[order_type::A] = SrcPixelFormatRenderer::base_mask; + } + else + { + SrcPixelFormatRenderer::blender_type::blend_pix(pDstBuffer, pSrcBuffer[order_type::R], pSrcBuffer[order_type::G], pSrcBuffer[order_type::B], uchAlpha); + } + } + + pSrcBuffer += nStep; + pDstBuffer += nStep; + } + } + } + private: + BYTE* m_pBuffer; + bool m_bExternalBuffer; + + TGraphicsLayerSettings m_oSettings; + }; + +} + +#endif // CGRAPHICSLAYER_H diff --git a/DesktopEditor/graphics/GraphicsRenderer.cpp b/DesktopEditor/graphics/GraphicsRenderer.cpp index 7304897791..ca30c7c629 100644 --- a/DesktopEditor/graphics/GraphicsRenderer.cpp +++ b/DesktopEditor/graphics/GraphicsRenderer.cpp @@ -799,6 +799,11 @@ HRESULT CGraphicsRenderer::BeginCommand(const DWORD& lType) m_pRenderer->CreateAlphaMask(); break; } + case c_nLayerType: + { + m_pRenderer->CreateLayer(); + break; + } default: break; }; @@ -838,6 +843,11 @@ HRESULT CGraphicsRenderer::EndCommand(const DWORD& lType) m_pRenderer->ResetAlphaMask(); break; } + case c_nLayerType: + { + m_pRenderer->BlendLayer(); + break; + } default: break; }; @@ -1406,6 +1416,11 @@ void CGraphicsRenderer::SetAlphaMask(Aggplus::CAlphaMask* pAlphaMask) m_pRenderer->SetAlphaMask(pAlphaMask); } +HRESULT CGraphicsRenderer::put_LayerOpacity(double dValue) +{ + return m_pRenderer->SetLayerOpacity(dValue); +} + void CGraphicsRenderer::put_GlobalAlphaEnabled(const bool& bEnabled, const double& dVal) { m_bGlobalAlphaEnabled = bEnabled; diff --git a/DesktopEditor/graphics/GraphicsRenderer.h b/DesktopEditor/graphics/GraphicsRenderer.h index e0d67d8628..eba5cc8647 100644 --- a/DesktopEditor/graphics/GraphicsRenderer.h +++ b/DesktopEditor/graphics/GraphicsRenderer.h @@ -352,6 +352,9 @@ public: // alpha mask methods void SetAlphaMask(Aggplus::CAlphaMask* pAlphaMask); + // layer methods + HRESULT put_LayerOpacity(double dValue); + // smart methods void drawHorLine(BYTE align, double y, double x, double r, double penW) { diff --git a/DesktopEditor/graphics/IRenderer.h b/DesktopEditor/graphics/IRenderer.h index 849f6e6d56..feb28daab3 100644 --- a/DesktopEditor/graphics/IRenderer.h +++ b/DesktopEditor/graphics/IRenderer.h @@ -67,6 +67,8 @@ const long c_nTableCell = 0x2000; const long c_nMaskType = 0x3000; const long c_nResetMaskType = 0x4000; +const long c_nLayerType = 0x5000; + const long c_nPDFTilingFill = 0x2001; const long c_nPDFTilingFillIteration = 0x2002; @@ -355,6 +357,9 @@ public: virtual HRESULT IsSupportAdvancedCommand(const IAdvancedCommand::AdvancedCommandType& type) { return S_FALSE; } virtual HRESULT AdvancedCommand(IAdvancedCommand* command) { return S_FALSE; } + + // graphics layer settings + virtual HRESULT put_LayerOpacity(double dValue) { return S_FALSE; } }; #define PROPERTY_RENDERER(NameBase, Name, Type) \ diff --git a/DesktopEditor/graphics/commands/AnnotField.cpp b/DesktopEditor/graphics/commands/AnnotField.cpp index 9c3f6782e4..6035767f1f 100644 --- a/DesktopEditor/graphics/commands/AnnotField.cpp +++ b/DesktopEditor/graphics/commands/AnnotField.cpp @@ -457,9 +457,12 @@ bool CAnnotFieldInfo::Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, IMeta { m_oBorder.nType = pReader->ReadByte(); m_oBorder.dWidth = pReader->ReadDouble(); - int n = pReader->ReadInt(); - for (int i = 0; i < n; ++i) - m_oBorder.arrDash.push_back(pReader->ReadDouble()); + if (m_oBorder.nType == 2) + { + int n = pReader->ReadInt(); + for (int i = 0; i < n; ++i) + m_oBorder.arrDash.push_back(pReader->ReadDouble()); + } } if (nFlags & (1 << 5)) m_wsLM = pReader->ReadString(); diff --git a/DesktopEditor/graphics/pro/graphics.pro b/DesktopEditor/graphics/pro/graphics.pro index ce20b972e5..096c52db19 100644 --- a/DesktopEditor/graphics/pro/graphics.pro +++ b/DesktopEditor/graphics/pro/graphics.pro @@ -1,4 +1,4 @@ -QT -= core gui +QT -= core gui TARGET = graphics TEMPLATE = lib @@ -7,12 +7,12 @@ CONFIG += graphics_dynamic_library DEFINES += _QT graphics_dynamic_library { - CONFIG += shared + CONFIG += shared CONFIG += plugin - DEFINES += GRAPHICS_USE_DYNAMIC_LIBRARY_BUILDING + DEFINES += GRAPHICS_USE_DYNAMIC_LIBRARY_BUILDING } else { - DEFINES += GRAPHICS_NO_USE_DYNAMIC_LIBRARY + DEFINES += GRAPHICS_NO_USE_DYNAMIC_LIBRARY CONFIG += static } @@ -23,7 +23,7 @@ include(../../../Common/base.pri) ADD_DEPENDENCY(UnicodeConverter, kernel) core_windows { - LIBS += -lAdvapi32 + LIBS += -lAdvapi32 LIBS += -lShell32 } @@ -32,39 +32,46 @@ HEADERS += ./../config.h GRAPHICS_AGG_PATH = $$PWD/../../agg-2.4 INCLUDEPATH += \ - $$GRAPHICS_AGG_PATH/include + $$GRAPHICS_AGG_PATH/include # matrix HEADERS += \ - $$GRAPHICS_AGG_PATH/include/test_grads/custom_gradients.h \ - ./../Matrix_private.h \ + $$GRAPHICS_AGG_PATH/include/test_grads/custom_gradients.h \ + ./../Matrix_private.h \ ./../Matrix.h SOURCES += \ - ./../Matrix.cpp + ./../Matrix.cpp SOURCES += \ - $$GRAPHICS_AGG_PATH/src/agg_trans_affine.cpp + $$GRAPHICS_AGG_PATH/src/agg_trans_affine.cpp # paths HEADERS += \ - ./../GraphicsPath_private.h \ + ./../GraphicsPath_private.h \ ./../GraphicsPath.h SOURCES += \ - ./../GraphicsPath.cpp + ./../GraphicsPath.cpp # alpha mask HEADERS += \ - ./../AlphaMask_private.h \ + ./../AlphaMask_private.h \ ./../AlphaMask.h SOURCES += \ - ./../AlphaMask_private.cpp \ + ./../AlphaMask_private.cpp \ ./../AlphaMask.cpp +# grapgics layer +HEADERS += \ + ./../GraphicsLayer.h + SOURCES += \ - $$GRAPHICS_AGG_PATH/src/agg_arc.cpp \ + ./../GraphicsLayer.cpp + +SOURCES += \ + $$GRAPHICS_AGG_PATH/src/agg_arc.cpp \ $$GRAPHICS_AGG_PATH/src/agg_bezier_arc.cpp \ $$GRAPHICS_AGG_PATH/src/agg_curves.cpp \ $$GRAPHICS_AGG_PATH/src/agg_bspline.cpp \ @@ -76,9 +83,9 @@ include(raster.pri) #CONFIG += graphics_disable_metafile graphics_disable_metafile { - DEFINES += GRAPHICS_DISABLE_METAFILE + DEFINES += GRAPHICS_DISABLE_METAFILE } else { - include(metafile.pri) + include(metafile.pri) } CONFIG += support_font_converter @@ -90,7 +97,7 @@ SOURCES += ./officedrawingfile.cpp # graphics SOURCES += \ - $$GRAPHICS_AGG_PATH/src/agg_arrowhead.cpp \ + $$GRAPHICS_AGG_PATH/src/agg_arrowhead.cpp \ $$GRAPHICS_AGG_PATH/src/agg_image_filters.cpp \ $$GRAPHICS_AGG_PATH/src/agg_line_aa_basics.cpp \ $$GRAPHICS_AGG_PATH/src/agg_line_profile_aa.cpp \ @@ -99,7 +106,7 @@ SOURCES += \ $$GRAPHICS_AGG_PATH/src/agg_vcgen_smooth_poly1.cpp HEADERS += \ - ./../ArrowHead.h \ + ./../ArrowHead.h \ ./../Brush.h \ ./../Clip.h \ ./../Color.h \ @@ -115,7 +122,7 @@ HEADERS += \ ./Image.h SOURCES += \ - ./../ArrowHead.cpp \ + ./../ArrowHead.cpp \ ./../Brush.cpp \ ./../Clip.cpp \ ./../Graphics.cpp \ diff --git a/DesktopEditor/graphics/pro/js/drawingfile.json b/DesktopEditor/graphics/pro/js/drawingfile.json index b8521a7c21..b5d73d545c 100644 --- a/DesktopEditor/graphics/pro/js/drawingfile.json +++ b/DesktopEditor/graphics/pro/js/drawingfile.json @@ -31,6 +31,7 @@ "_GetLinks", "_GetStructure", "_GetInteractiveFormsInfo", + "_GetInteractiveFormsFonts", "_GetInteractiveFormsAP", "_GetButtonIcons", "_GetAnnotationsInfo", @@ -39,6 +40,7 @@ "_InitializeFontsBase64", "_InitializeFontsRanges", "_SetFontBinary", + "_GetFontBinary", "_IsFontBinaryExist", "_DestroyTextInfo", "_IsNeedCMap", diff --git a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_base.js b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_base.js index a2e4a1f95f..11762b97f1 100644 --- a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_base.js +++ b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_base.js @@ -845,6 +845,41 @@ Module["_free"](ext); return res; }; + CFile.prototype["getInteractiveFormsFonts"] = function() + { + let res = []; + let ext = Module["_GetInteractiveFormsFonts"](this.nativeFile); + if (ext == 0) + return res; + + let lenArray = new Int32Array(Module["HEAP8"].buffer, ext, 4); + if (lenArray == null) + { + Module["_free"](ext); + return res; + } + + let len = lenArray[0]; + len -= 4; + if (len <= 0) + { + Module["_free"](ext); + return res; + } + + let buffer = new Uint8Array(Module["HEAP8"].buffer, ext + 4, len); + let reader = new CBinaryReader(buffer, 0, len); + + while (reader.isValid()) + { + let n = reader.readInt(); + for (let i = 0; i < n; ++i) + res.push(reader.readString()); + } + + Module["_free"](ext); + return res; + }; // optional nWidget - rec["AP"]["i"] // optional sView - N/D/R // optional sButtonView - state pushbutton-annotation - Off/Yes(or rec["ExportValue"]) @@ -1322,6 +1357,53 @@ Module["_free"](str); return res; }; + CFile.prototype["getFontByID"] = function(ID) + { + let res = null; + if (ID === undefined) + return res; + + let idBuffer = ID.toUtf8(); + let idPointer = Module["_malloc"](idBuffer.length); + Module["HEAP8"].set(idBuffer, idPointer); + + let ext = Module["_GetFontBinary"](idPointer); + if (ext == 0) + return res; + + let lenArray = new Int32Array(Module["HEAP8"].buffer, ext, 4); + if (lenArray == null) + { + Module["_free"](ext); + return res; + } + + let len = lenArray[0]; + len -= 4; + if (len <= 0) + { + Module["_free"](ext); + return res; + } + + let buffer = new Uint8Array(Module["HEAP8"].buffer, ext + 4, len); + let reader = new CBinaryReader(buffer, 0, len); + + while (reader.isValid()) + { + let nFontLength = reader.readInt(); + let np1 = reader.readInt(); + let np2 = reader.readInt(); + let pFontPoint = np2 << 32 | np1; + + res = new Uint8Array(Module["HEAP8"].buffer, pFontPoint, nFontLength); + } + + Module["_free"](idPointer); + Module["_free"](ext); + + return res; + }; CFile.prototype.memory = function() { diff --git a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp index 909c4b4c59..32788a3dbc 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp @@ -57,6 +57,39 @@ WASM_EXPORT void SetFontBinary(char* path, BYTE* data, int size) pStorage->Add(UTF8_TO_U(sPathA), data, size, true); } } +WASM_EXPORT BYTE* GetFontBinary(char* path) +{ + NSWasm::CData oRes; + oRes.SkipLen(); + + NSFonts::IFontsMemoryStorage* pStorage = NSFonts::NSApplicationFontStream::GetGlobalMemoryStorage(); + if (pStorage) + { + std::string sPathA(path); + NSFonts::IFontStream* pStream = pStorage->Get(UTF8_TO_U(sPathA)); + if (pStream) + { + BYTE* pData = NULL; + LONG lLength = 0; + pStream->GetMemory(pData, lLength); + + if (pData) + { + oRes.AddInt(lLength); + + unsigned long long npSubMatrix = (unsigned long long)pData; + unsigned int npSubMatrix1 = npSubMatrix & 0xFFFFFFFF; + oRes.AddInt(npSubMatrix1); + oRes.AddInt(npSubMatrix >> 32); + } + } + } + + oRes.WriteLen(); + BYTE* bRes = oRes.GetBuffer(); + oRes.ClearWithoutAttack(); + return bRes; +} WASM_EXPORT int IsFontBinaryExist(char* path) { NSFonts::IFontsMemoryStorage* pStorage = NSFonts::NSApplicationFontStream::GetGlobalMemoryStorage(); @@ -156,6 +189,10 @@ WASM_EXPORT BYTE* GetInteractiveFormsInfo(CGraphicsFileDrawing* pGraphics) { return pGraphics->GetInteractiveFormsInfo(); } +WASM_EXPORT BYTE* GetInteractiveFormsFonts(CGraphicsFileDrawing* pGraphics) +{ + return pGraphics->GetWidgetFontsID(); +} WASM_EXPORT BYTE* GetInteractiveFormsAP(CGraphicsFileDrawing* pGraphics, int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nWidget, int nView, int nButtonView) { const char* sView = NULL; diff --git a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.h b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.h index 7d2dccf469..aea2993e95 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.h +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.h @@ -123,6 +123,12 @@ public: return ((CPdfFile*)pReader)->GetWidgets(); return NULL; } + BYTE* GetWidgetFontsID() + { + if (nType == 0) + return ((CPdfFile*)pReader)->GetWidgetFonts(); + return NULL; + } BYTE* GetAnnots(int nPageIndex = -1) { if (nType == 0) diff --git a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp index 20dfa05b8e..d4f2db4a2f 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp @@ -651,10 +651,11 @@ void ReadAnnotAP(BYTE* pWidgetsAP, int& i) int nAPLength = READ_INT(pWidgetsAP + i); i += 4; + if (nAPLength > 0) + std::cout << "APName "; for (int j = 0; j < nAPLength; ++j) { - std::cout << std::endl; nPathLength = READ_INT(pWidgetsAP + i); i += 4; std::string sAPName = std::string((char*)(pWidgetsAP + i), nPathLength); @@ -665,7 +666,7 @@ void ReadAnnotAP(BYTE* pWidgetsAP, int& i) sAPName += nPathLength ? ("." + std::string((char*)(pWidgetsAP + i), nPathLength)) : ""; i += nPathLength; - std::cout << "APName " << sAPName << ", "; + std::cout << sAPName << ", "; unsigned long long npBgraData1 = READ_INT(pWidgetsAP + i); i += 4; unsigned long long npBgraData2 = READ_INT(pWidgetsAP + i); @@ -774,7 +775,7 @@ int main(int argc, char* argv[]) std::cout << " Page " << nTestPage << " width " << nWidth << " height " << nHeight << " dpi " << dpi << " rotate " << rotate << std::endl; nLength = READ_INT(pInfo + nPagesCount * 16 + 12); - std::cout << "json "<< std::string((char*)(pInfo + nPagesCount * 16 + 16), nLength) << std::endl;; + std::cout << "json "<< std::string((char*)(pInfo + nPagesCount * 16 + 16), nLength) << std::endl << std::endl; } } @@ -886,9 +887,57 @@ int main(int argc, char* argv[]) // INTERACTIVE FORMS if (true) { + BYTE* pFonts = GetInteractiveFormsFonts(pGrFile); + nLength = READ_INT(pFonts); + int i = 4; + nLength -= 4; + + while (i < nLength) + { + int nFontsLength = READ_INT(pFonts + i); + i += 4; + std::cout << "Fonts"; + + for (int j = 0; j < nFontsLength; ++j) + { + int nPathLength = READ_INT(pFonts + i); + i += 4; + std::string sFontName = std::string((char*)(pFonts + i), nPathLength); + std::cout << " " << sFontName; + i += nPathLength; + + BYTE* pFont = GetFontBinary((char*)sFontName.c_str()); + int nLength2 = READ_INT(pFont); + int i2 = 4; + nLength2 -= 4; + + while (i2 < nLength2) + { + int nFontLength = READ_INT(pFont + i2); + i2 += 4; + + unsigned long long npFont1 = READ_INT(pFont + i2); + i2 += 4; + unsigned long long npFont2 = READ_INT(pFont + i2); + i2 += 4; + + BYTE* res = (BYTE*)(npFont2 << 32 | npFont1); + + NSFile::CFileBinary oFile; + if (oFile.CreateFileW(NSFile::GetProcessDirectory() + L"/font" + std::to_wstring(j) + L".txt")) + oFile.WriteFile(res, nFontLength); + oFile.CloseFile(); + } + } + std::cout << std::endl; + } + + if (pFonts) + free(pFonts); + BYTE* pWidgets = GetInteractiveFormsInfo(pGrFile); nLength = READ_INT(pWidgets); - int i = 4; + i = 4; nLength -= 4; if (i < nLength) diff --git a/DesktopEditor/graphics/tests/graphicsLayers/graphicsLayers.pro b/DesktopEditor/graphics/tests/graphicsLayers/graphicsLayers.pro new file mode 100644 index 0000000000..2787314412 --- /dev/null +++ b/DesktopEditor/graphics/tests/graphicsLayers/graphicsLayers.pro @@ -0,0 +1,26 @@ +#CONFIG += c++11 cmdline + +#SOURCES += \ +QT -= core + +QT -= gui + +TARGET = test +CONFIG += console +TEMPLATE = app + +CORE_ROOT_DIR = $$PWD/../../../.. +PWD_ROOT_DIR = $$PWD +include($$CORE_ROOT_DIR/Common/base.pri) +include($$CORE_ROOT_DIR/Common/3dParty/icu/icu.pri) + +ADD_DEPENDENCY(kernel, graphics, UnicodeConverter) + +GRAPHICS_AGG_PATH = $$PWD/../../../agg-2.4 + +INCLUDEPATH += \ + $$GRAPHICS_AGG_PATH/include + +SOURCES += main.cpp + +DESTDIR = $$PWD_ROOT_DIR/build/$$CORE_BUILDS_PLATFORM_PREFIX/$$CORE_BUILDS_CONFIGURATION_PREFIX diff --git a/DesktopEditor/graphics/tests/graphicsLayers/main.cpp b/DesktopEditor/graphics/tests/graphicsLayers/main.cpp new file mode 100644 index 0000000000..34d875eae6 --- /dev/null +++ b/DesktopEditor/graphics/tests/graphicsLayers/main.cpp @@ -0,0 +1,108 @@ +#include "../../pro/Graphics.h" +#include "../../../raster/BgraFrame.h" +#include "../../../common/Directory.h" + +#define RGB_TO_INT(r, g, b) ((unsigned int)( ( (unsigned char)(r) )| ( ( (unsigned char)(g) ) << 8 ) | ( ( (unsigned char)(b) ) << 16 ) | ( (unsigned char)(0) << 24 ) ) ) + +int main(int argc, char *argv[]) +{ + NSGraphics::IGraphicsRenderer* pRasterRenderer = NSGraphics::Create(); + + const unsigned int unWidth = 1000; + const unsigned int unHeight = 1000; + + // Создание основной картинки + BYTE* pData = new BYTE[4 * unWidth * unHeight]; + + for (unsigned long unIndex = 0; unIndex < unWidth * unHeight; ++unIndex) + ((unsigned int*)pData)[unIndex] = 0xffffff; + + CBgraFrame oFrame; + oFrame.put_Data(pData); + oFrame.put_Width(unWidth); + oFrame.put_Height(unHeight); + oFrame.put_Stride(4 * unWidth); + + pRasterRenderer->CreateFromBgraFrame(&oFrame); + pRasterRenderer->SetSwapRGB(false); + + double dW_MM = unWidth; + double dH_MM = unHeight; + + pRasterRenderer->put_Width(dW_MM); + pRasterRenderer->put_Height(dH_MM); + + pRasterRenderer->BeginCommand(c_nPathType); + pRasterRenderer->PathCommandStart(); + + // Отрисовываем основной слой + pRasterRenderer->PathCommandRect(50, 200, 600, 300); + + pRasterRenderer->put_BrushAlpha1(255); + pRasterRenderer->put_BrushColor1(RGB_TO_INT(255, 0, 0)); // красный + + pRasterRenderer->put_PenAlpha(255); + pRasterRenderer->put_PenColor(RGB_TO_INT(255, 0, 255)); + pRasterRenderer->put_PenSize(40); + + pRasterRenderer->DrawPath(c_nWindingFillMode | c_nStroke); + + pRasterRenderer->PathCommandEnd(); + pRasterRenderer->EndCommand(c_nPathType); + + // Отрисовываем второй слой + pRasterRenderer->BeginCommand(c_nLayerType); + + pRasterRenderer->BeginCommand(c_nPathType); + pRasterRenderer->PathCommandStart(); + + pRasterRenderer->PathCommandRect(300, 300, 300, 300); + + pRasterRenderer->put_BrushAlpha1(255); + pRasterRenderer->put_BrushColor1(RGB_TO_INT(0, 255, 0)); // зеленый + + pRasterRenderer->put_PenAlpha(150); + pRasterRenderer->put_PenColor(RGB_TO_INT(0, 0, 255)); + pRasterRenderer->put_PenSize(40); + + pRasterRenderer->put_LayerOpacity(0.5); + + pRasterRenderer->DrawPath(c_nWindingFillMode | c_nStroke); + + pRasterRenderer->PathCommandEnd(); + pRasterRenderer->EndCommand(c_nPathType); + + //Отрисовываем третий слой + pRasterRenderer->BeginCommand(c_nLayerType); + + pRasterRenderer->BeginCommand(c_nPathType); + pRasterRenderer->PathCommandStart(); + + pRasterRenderer->PathCommandRect(500, 400, 300, 300); + + pRasterRenderer->put_BrushAlpha1(150); + pRasterRenderer->put_BrushColor1(RGB_TO_INT(0, 0, 255)); // синий + + pRasterRenderer->put_PenAlpha(255); + pRasterRenderer->put_PenColor(RGB_TO_INT(255, 0, 0)); + pRasterRenderer->put_PenSize(40); + + pRasterRenderer->put_LayerOpacity(1); + + pRasterRenderer->DrawPath(c_nWindingFillMode | c_nStroke); + + pRasterRenderer->PathCommandEnd(); + pRasterRenderer->EndCommand(c_nPathType); + + // блитируем трутий слой на второй + pRasterRenderer->EndCommand(c_nLayerType); + + // блитируем второй слой на основной + pRasterRenderer->EndCommand(c_nLayerType); + + oFrame.SaveFile(L"testGraphicsLayers.png", 4); + + RELEASEINTERFACE(pRasterRenderer); + + return 0; +} diff --git a/DesktopEditor/raster/Metafile/svg/SvgObjects/CObjectBase.cpp b/DesktopEditor/raster/Metafile/svg/SvgObjects/CObjectBase.cpp index 50f33ab399..2cf135dcbf 100644 --- a/DesktopEditor/raster/Metafile/svg/SvgObjects/CObjectBase.cpp +++ b/DesktopEditor/raster/Metafile/svg/SvgObjects/CObjectBase.cpp @@ -68,7 +68,7 @@ namespace SVG SetData(NSCSS::NS_STATIC_FUNCTIONS::GetRules(wsStyles), ushLevel, bHardMode); } - + void CObject::SetTransform(const std::map &mAttributes, unsigned short ushLevel, bool bHardMode) { if (mAttributes.end() != mAttributes.find(L"transform")) @@ -112,6 +112,12 @@ namespace SVG m_oTransformtaion.m_bDraw = true; } + void CObject::SetOpacity(const std::map &mAttributes, unsigned short ushLevel, bool bHardMode) + { + if (mAttributes.end() != mAttributes.find(L"opacity")) + m_oTransformtaion.m_oOpacity.SetValue(mAttributes.at(L"opacity"), ushLevel, bHardMode); + } + bool CObject::ApplyTransform(IRenderer *pRenderer, const NSCSS::NSProperties::CTransform *pTransform, Aggplus::CMatrix& oOldMatrix) const { if (NULL == pRenderer || NULL == pTransform) @@ -147,7 +153,7 @@ namespace SVG pRenderer->BeginCommand(c_nResetClipType); pRenderer->EndCommand(c_nResetClipType); - + return ApplyDef(pRenderer, pFile, pClip->m_oHref.ToWString(), oBounds); } @@ -205,9 +211,10 @@ namespace SVG void CRenderedObject::SetData(const std::map &mAttributes, unsigned short ushLevel, bool bHardMode) { SetTransform(mAttributes, ushLevel, bHardMode); - SetDisplay(mAttributes, ushLevel, bHardMode); - SetClip(mAttributes, ushLevel, bHardMode); - SetMask(mAttributes, ushLevel, bHardMode); + SetDisplay (mAttributes, ushLevel, bHardMode); + SetOpacity (mAttributes, ushLevel, bHardMode); + SetClip (mAttributes, ushLevel, bHardMode); + SetMask (mAttributes, ushLevel, bHardMode); } std::vector CRenderedObject::GetFullPath() const @@ -229,7 +236,8 @@ namespace SVG m_oStyles.m_oStroke.m_oLineCap = Aggplus::LineJoinMiter; m_oStyles.m_oStroke.m_oMiterlimit = 4.; - + + m_oTransformtaion.m_oOpacity = 1.; m_oTransformtaion.m_bDraw = true; } @@ -267,14 +275,11 @@ namespace SVG if (mAttributes.end() != mAttributes.find(L"fill-opacity")) m_oStyles.m_oFill.SetOpacity(mAttributes.at(L"fill-opacity"), ushLevel, bHardMode); - - if (mAttributes.end() != mAttributes.find(L"opacity")) - m_oStyles.m_oFill.SetOpacity(mAttributes.at(L"opacity"), ushLevel, bHardMode); } bool CRenderedObject::StartPath(IRenderer *pRenderer, const CSvgFile *pFile, Aggplus::CMatrix &oOldTransform, CommandeMode oMode) const { - if (NULL == pRenderer || !m_oTransformtaion.m_bDraw) + if (NULL == pRenderer || !m_oTransformtaion.m_bDraw || Equals(0., m_oTransformtaion.m_oOpacity.ToDouble())) return false; ApplyTransform(pRenderer, &m_oTransformtaion.m_oTransform, oOldTransform); @@ -283,6 +288,11 @@ namespace SVG if (CommandeModeClip == oMode) pRenderer->BeginCommand(c_nClipType); + else if (1. != m_oTransformtaion.m_oOpacity.ToDouble()) + { + pRenderer->BeginCommand(c_nLayerType); + pRenderer->put_LayerOpacity(m_oTransformtaion.m_oOpacity.ToDouble()); + } pRenderer->BeginCommand(c_nPathType); pRenderer->PathCommandStart(); @@ -300,7 +310,7 @@ namespace SVG pRenderer->SetTransform(oOldTransform.sx(), oOldTransform.shy(), oOldTransform.shx(), oOldTransform.sy(), oOldTransform.tx(), oOldTransform.ty()); return; } - + int nPathType = 0; if (NULL == pOtherStyles) @@ -327,6 +337,9 @@ namespace SVG pRenderer->BeginCommand(c_nResetMaskType); pRenderer->EndCommand(c_nResetMaskType); } + + if (1. != m_oTransformtaion.m_oOpacity.ToDouble()) + pRenderer->EndCommand(c_nLayerType); pRenderer->SetTransform(oOldTransform.sx(), oOldTransform.shy(), oOldTransform.shx(), oOldTransform.sy(), oOldTransform.tx(), oOldTransform.ty()); } diff --git a/DesktopEditor/raster/Metafile/svg/SvgObjects/CObjectBase.h b/DesktopEditor/raster/Metafile/svg/SvgObjects/CObjectBase.h index 41a4ceca0e..70593e6938 100644 --- a/DesktopEditor/raster/Metafile/svg/SvgObjects/CObjectBase.h +++ b/DesktopEditor/raster/Metafile/svg/SvgObjects/CObjectBase.h @@ -24,6 +24,7 @@ namespace SVG SvgTransform m_oTransform; TClip m_oClip; SvgColor m_oMask; + SvgDigit m_oOpacity; bool m_bDraw; }; @@ -49,7 +50,8 @@ namespace SVG void SetTransform(const std::map& mAttributes, unsigned short ushLevel, bool bHardMode = false); void SetClip(const std::map& mAttributes, unsigned short ushLevel, bool bHardMode = false); void SetMask(const std::map& mAttributes, unsigned short ushLevel, bool bHardMode = false); - void SetDisplay(const std::map& mAttributes, unsigned short ushLevel, bool bHardMode = false); + void SetDisplay(const std::map& mAttributes, unsigned short ushLevel, bool bHardMode = false); + void SetOpacity(const std::map& mAttributes, unsigned short ushLevel, bool bHardMode = false); std::wstring GetId() const; virtual std::vector GetFullPath() const; diff --git a/MsBinaryFile/PptFile/Reader/PPTDocumentInfoOneUser.cpp b/MsBinaryFile/PptFile/Reader/PPTDocumentInfoOneUser.cpp index 7b2465c9c8..5dfd3d5a86 100644 --- a/MsBinaryFile/PptFile/Reader/PPTDocumentInfoOneUser.cpp +++ b/MsBinaryFile/PptFile/Reader/PPTDocumentInfoOneUser.cpp @@ -546,7 +546,10 @@ void CPPTUserInfo::FromDocument() if (0 != oArrayHeadersFootersInfo.size()) { - for (int i = 0; i < 3; i++) m_PlaceholdersReplaceString[i] = oArrayHeadersFootersInfo[0]->m_HeadersFootersString[i]; + for (int i = 0; i < 3; i++) + { + m_PlaceholdersReplaceString[i] = oArrayHeadersFootersInfo[0]->m_HeadersFootersString[i]; + } if (oArrayHeadersFootersInfo[0]->m_oHeadersFootersAtom) { @@ -574,6 +577,18 @@ void CPPTUserInfo::FromDocument() m_bRtl = (oArrayDoc[0]->m_bRightToLeft != 0); m_bShowComments = (oArrayDoc[0]->m_bShowComments != 0); + for (size_t i = 0; i < m_arrSlidesOrder.size(); i++) + { + std::map<_UINT32, CRecordSlide*>::iterator pPair = m_mapSlides.find(m_arrSlidesOrder[i]); + + if (pPair == m_mapSlides.end()) + continue; + + LoadSlideFromPrevUsers(pPair->first); + + TestSlide(pPair->first); + } + LoadMasters(); double DurationSlide = PPT_DEFAULT_SLIDE_DURATION; @@ -804,8 +819,33 @@ void CPPTUserInfo::LoadNotes(_UINT32 dwNoteID, CSlide* pNotes) } } } +void CPPTUserInfo::TestSlide(_UINT32 dwSlideID) +{ + std::map<_UINT32, CRecordSlide*>::iterator pPairSlide = m_mapSlides.find(dwSlideID); + if (pPairSlide == m_mapSlides.end()) return; + CRecordSlide* pRecordSlide = pPairSlide->second; + if (NULL == pRecordSlide) return; + + std::vector oArraySlideAtoms; + pRecordSlide->GetRecordsByType(&oArraySlideAtoms, false, true); + if (0 == oArraySlideAtoms.size()) + { + // ошибка!!! + return; + } + std::map<_UINT32, LONG>::iterator pFind = m_mapRealUsedMaster.find(oArraySlideAtoms[0]->m_nMasterIDRef); + + if (pFind == m_mapRealUsedMaster.end()) + { + m_mapRealUsedMaster.insert(std::make_pair(oArraySlideAtoms[0]->m_nMasterIDRef, 1)); + } + else + { + pFind->second++; + } +} void CPPTUserInfo::LoadSlide(_UINT32 dwSlideID, CSlide* pSlide) { std::map<_UINT32, CRecordSlide*>::iterator pPairSlide = m_mapSlides.find(dwSlideID); @@ -1673,9 +1713,10 @@ void CPPTUserInfo::LoadMainMaster(_UINT32 dwMasterID, bool alwaysLoad) void CPPTUserInfo::LoadMasters() { - for (size_t i = 0; i < m_arrMastersOrder.size(); i++) + //for (size_t i = 0; i < m_arrMastersOrder.size(); i++) + for (auto master : m_mapRealUsedMaster) { - std::map<_UINT32, CRecordSlide*>::iterator pPair = m_mapMasters.find(m_arrMastersOrder[i]); + std::map<_UINT32, CRecordSlide*>::iterator pPair = m_mapMasters.find(master.first/*m_arrMastersOrder[i]*/); if (pPair == m_mapMasters.end())continue; LoadMainMaster(pPair->first, false); @@ -1683,9 +1724,10 @@ void CPPTUserInfo::LoadMasters() if (m_mapMasterToTheme.empty()) { - for (size_t i = 0; i < m_arrMastersOrder.size(); i++) + // for (size_t i = 0; i < m_arrMastersOrder.size(); i++) + for (auto master : m_mapRealUsedMaster) { - std::map<_UINT32, CRecordSlide*>::iterator pPair = m_mapMasters.find(m_arrMastersOrder[i]); + std::map<_UINT32, CRecordSlide*>::iterator pPair = m_mapMasters.find(master.first/*m_arrMastersOrder[i]*/); if (pPair == m_mapMasters.end())continue; LoadMainMaster(pPair->first, true); @@ -2592,7 +2634,7 @@ void CPPTUserInfo::AddAudioTransition(_UINT32 refID, CTransition* pTransition, c std::vector sound; m_oDocument.GetRecordsByType(&sound, false); - if (sound.empty() || sound[0]->m_arRecords.size() < refID) + if (sound.empty() || sound[0]->m_arRecords.size() <= refID) return; auto audio = dynamic_cast(sound[0]->m_arRecords[refID]); diff --git a/MsBinaryFile/PptFile/Reader/PPTDocumentInfoOneUser.h b/MsBinaryFile/PptFile/Reader/PPTDocumentInfoOneUser.h index d4928ae63d..18221edeef 100644 --- a/MsBinaryFile/PptFile/Reader/PPTDocumentInfoOneUser.h +++ b/MsBinaryFile/PptFile/Reader/PPTDocumentInfoOneUser.h @@ -76,6 +76,8 @@ public: // перевод id мастера в индекс темы/шаблона std::map<_UINT32, LONG> m_mapMasterToTheme; + std::map<_UINT32, LONG> m_mapRealUsedMaster; + // original id -> natural id std::map<_UINT32, _UINT32> m_mapMasterOriginalIds; @@ -140,6 +142,8 @@ public: void LoadSlide(_UINT32 dwSlideID, CSlide* pSlide); void LoadNotes(_UINT32 dwNotesID, CSlide* pSlide); + void TestSlide(_UINT32 dwSlideID); + void LoadMasters(); void LoadNoMainMaster (_UINT32 dwMasterID); diff --git a/OdfFile/DataTypes/presentationclass.cpp b/OdfFile/DataTypes/presentationclass.cpp index b1054b8daf..6b2e55635e 100644 --- a/OdfFile/DataTypes/presentationclass.cpp +++ b/OdfFile/DataTypes/presentationclass.cpp @@ -95,8 +95,8 @@ std::wstring presentation_class::get_type_ms() case title: res = L"title"; break; - // case subtitle: - //res = L"subTitle"; + case subtitle: + res = L"body"; break; case graphic: res = L"body"; @@ -125,7 +125,6 @@ std::wstring presentation_class::get_type_ms() case page_number: res = L"sldNum"; break; - case subtitle: case notes: case handout: case outline: diff --git a/OdfFile/Reader/Converter/pptx_conversion_context.cpp b/OdfFile/Reader/Converter/pptx_conversion_context.cpp index 0b28fb6b7e..cd06a9bd62 100644 --- a/OdfFile/Reader/Converter/pptx_conversion_context.cpp +++ b/OdfFile/Reader/Converter/pptx_conversion_context.cpp @@ -45,47 +45,46 @@ #include "pptx_default_serializes.h" -namespace cpdoccore { +namespace cpdoccore { -namespace odf_reader -{ - class odf_document; -} + namespace odf_reader + { + class odf_document; + } -namespace oox { - -namespace package -{ - class pptx_document; -} + namespace oox { -pptx_conversion_context::pptx_conversion_context( odf_reader::odf_document * odfDocument) - :output_document_ (NULL) - ,odf_document_ (odfDocument) - ,pptx_text_context_ (odf_document_->odf_context(), *this) - ,pptx_table_context_ (*this) - ,pptx_comments_context_ (comments_context_handle_) - ,pptx_slide_context_ (*this/*, pptx_text_context_*/) - ,math_context_ (odf_document_->odf_context().fontContainer(), true) - ,last_idx_placeHolder (1) - ,last_uniq_big_id (1) -{ -} + namespace package + { + class pptx_document; + } -pptx_conversion_context::~pptx_conversion_context() -{ -} + pptx_conversion_context::pptx_conversion_context(odf_reader::odf_document* odfDocument) + :output_document_(NULL) + , odf_document_(odfDocument) + , pptx_text_context_(odf_document_->odf_context(), *this) + , pptx_table_context_(*this) + , pptx_comments_context_(comments_context_handle_) + , pptx_slide_context_(*this/*, pptx_text_context_*/) + , math_context_(odf_document_->odf_context().fontContainer(), true) + , last_idx_placeHolder(1) + , last_uniq_big_id(1) + { + } -void pptx_conversion_context::set_output_document(package::pptx_document * document) -{ - output_document_ = document; -} + pptx_conversion_context::~pptx_conversion_context() + { + } -void pptx_conversion_context::set_font_directory(std::wstring pathFonts) -{ - pptx_slide_context_.get_mediaitems()->set_font_directory(pathFonts); -} + void pptx_conversion_context::set_output_document(package::pptx_document* document) + { + output_document_ = document; + } + void pptx_conversion_context::set_font_directory(std::wstring pathFonts) + { + pptx_slide_context_.get_mediaitems()->set_font_directory(pathFonts); + } void pptx_conversion_context::add_page_name(const std::wstring& page_name) { page_names_.push_back(page_name); @@ -96,629 +95,632 @@ const std::vector& pptx_conversion_context::get_page_names() const return page_names_; } -void pptx_conversion_context::process_layouts() -{ - odf_reader::presentation_layouts_instance & layouts = root()->odf_context().styleContainer().presentation_layouts(); - - get_text_context().set_process_layouts(true); - - //актуальные - for (size_t layout_index =0; layout_index < layouts.content.size(); layout_index++) - { - start_layout(layout_index); - - odf_reader::style_presentation_page_layout * layout = - root()->odf_context().pageLayoutContainer().presentation_page_layout_by_name(layouts.content[layout_index].layout_name); - - if (layout) + void pptx_conversion_context::process_layouts() { - layout->pptx_convert(*this); - } - //нужно вытащить footers - odf_reader::style_master_page * master = - root()->odf_context().pageLayoutContainer().master_page_by_name(layouts.content[layout_index].master_name); + odf_reader::presentation_layouts_instance& layouts = root()->odf_context().styleContainer().presentation_layouts(); - if (master) - { - for (size_t i = 0; i < master->content_.size(); i++) + get_text_context().set_process_layouts(true); + + //актуальные + for (size_t layout_index = 0; layout_index < layouts.content.size(); layout_index++) { - odf_reader::draw_frame* frame = dynamic_cast(master->content_[i].get()); - if (frame) + start_layout(layout_index); + + odf_reader::style_presentation_page_layout* layout = + root()->odf_context().pageLayoutContainer().presentation_page_layout_by_name(layouts.content[layout_index].layout_name); + + if (layout) { - odf_types::common_presentation_attlist &common_presentation_attlist_= frame->common_draw_attlists_.shape_with_text_and_styles_.common_presentation_attlist_; - - if (common_presentation_attlist_.presentation_class_) + layout->pptx_convert(*this); + } + //нужно вытащить footers + odf_reader::style_master_page* master = + root()->odf_context().pageLayoutContainer().master_page_by_name(layouts.content[layout_index].master_name); + + if (master) + { + for (size_t i = 0; i < master->content_.size(); i++) { - odf_types::presentation_class::type type = common_presentation_attlist_.presentation_class_->get_type(); - - if (type == odf_types::presentation_class::footer || - type == odf_types::presentation_class::date_time || - type == odf_types::presentation_class::header || - type == odf_types::presentation_class::page_number) + odf_reader::draw_frame* frame = dynamic_cast(master->content_[i].get()); + if (frame) { - if (frame->idx_in_owner < 0) - frame->idx_in_owner = last_idx_placeHolder++; + odf_types::common_presentation_attlist& common_presentation_attlist_ = frame->common_draw_attlists_.shape_with_text_and_styles_.common_presentation_attlist_; - frame->pptx_convert_placeHolder(*this); + if (common_presentation_attlist_.presentation_class_) + { + odf_types::presentation_class::type type = common_presentation_attlist_.presentation_class_->get_type(); + + if (type == odf_types::presentation_class::footer || + type == odf_types::presentation_class::date_time || + type == odf_types::presentation_class::header || + type == odf_types::presentation_class::page_number) + { + if (frame->idx_in_owner < 0) + frame->idx_in_owner = last_idx_placeHolder++; + + frame->pptx_convert_placeHolder(*this); + } + } } } } + end_layout(); } + get_text_context().set_process_layouts(false); } - end_layout(); - } - get_text_context().set_process_layouts(false); -} -void pptx_conversion_context::process_master_pages() -{ - odf_reader::presentation_masters_instance & masters = root()->odf_context().styleContainer().presentation_masters(); - - process_masters_ = true; - get_text_context().set_process_layouts(true); - - //берем только актуальные - odf_reader::office_element_ptr master_notes_; - - for (size_t master_index = 0; master_index < masters.content.size(); master_index++) - { - start_master(master_index); - - odf_reader::style_master_page * master = - root()->odf_context().pageLayoutContainer().master_page_by_name(masters.content[master_index].master_name); - - if (master) + void pptx_conversion_context::process_master_pages() { - master->pptx_convert(*this); - - if (!master_notes_ && master->presentation_notes_) - master_notes_ = master->presentation_notes_; - } + odf_reader::presentation_masters_instance& masters = root()->odf_context().styleContainer().presentation_masters(); - - end_master(); - } + process_masters_ = true; + get_text_context().set_process_layouts(true); - if (master_notes_) - { - start_master_notes(); - master_notes_->pptx_convert(*this); - end_master_notes(); - } - process_masters_ = false; - get_text_context().set_process_layouts(false); + //берем только актуальные + odf_reader::office_element_ptr master_notes_; -} - -void pptx_conversion_context::process_styles() -{ - -} -void pptx_conversion_context::process_theme(std::wstring name) -{ - int current = themes_.size() + 1; - - if (name.empty()) - { - name = L"User Theme: " + std::to_wstring(current); - } - start_theme(name); - // - pptx_serialize_clrScheme (current_theme().clrSchemeData()); - pptx_serialize_fmtScheme (current_theme().fmtSchemeData()); - pptx_serialize_fontScheme (current_theme().fontSchemeData()); - // - end_theme(); - -} -void pptx_conversion_context::start_document() -{ - odf_reader::odf_read_context & odfContext = root()->odf_context(); - std::vector instances; - - instances.push_back(odfContext.styleContainer().style_default_by_type(odf_types::style_family::Presentation)); - instances.push_back(odfContext.styleContainer().style_by_name(L"Default", odf_types::style_family::Presentation, false)); - - odf_reader::text_format_properties_ptr textFormatProperties = calc_text_properties_content(instances); - odf_reader::paragraph_format_properties parFormatProperties = calc_paragraph_properties_content(instances); - - process_masters_ = false; -} - -void pptx_conversion_context::end_document() -{ - for (size_t i = 0; i < slideMasters_.size(); i++) - { - pptx_xml_slideMaster_ptr& slideM = slideMasters_[i]; - - package::slide_content_ptr content = package::slide_content::create(); - - slideM->write_to(content->content()); - content->add_rels(slideM->Rels());//media & links rels - - output_document_->get_ppt_files().add_slideMaster(content);//slideMaster.xml - - CP_XML_WRITER(presentation_.slideMastersData())//presentation.xml - { - CP_XML_NODE(L"p:sldMasterId") - { - CP_XML_ATTR(L"id", 0x80000000 + last_uniq_big_id++); - CP_XML_ATTR(L"r:id", slideM->rId()); - } - } - } - if (!slideMasters_.empty()) - presentation_.slidesProperties() << slideMasters_[0]->Sizes().str(); - -//////////////////////////////////////////////////////////////////////////////////////////////////// - for (size_t i = 0; i < slides_.size(); i++) - { - pptx_xml_slide_ptr& slide = slides_[i]; - - package::slide_content_ptr content = package::slide_content::create(); - - slide->write_to(content->content()); - content->add_rels(slide->Rels());//media & links rels - - output_document_->get_ppt_files().add_slide(content);//slide.xml - - CP_XML_WRITER(presentation_.slidesData())//presentation.xml - { - CP_XML_NODE(L"p:sldId") - { - CP_XML_ATTR(L"id", 0x100 + i); - CP_XML_ATTR(L"r:id", slide->rId()); - } - } - } -//---------------------------------------------------------------------------------- - for (size_t i = 0; i < slideLayouts_.size(); i++) - { - pptx_xml_slideLayout_ptr& slideL = slideLayouts_[i]; - - package::slide_content_ptr content = package::slide_content::create(); - - slideL->write_to(content->content()); - content->add_rels(slideL->Rels());//media & links rels - - output_document_->get_ppt_files().add_slideLayout(content);//slideMaster.xml - } -//---------------------------------------------------------------------------------- - for (size_t i = 0; i < notes_.size(); i++) - { - pptx_xml_slideNotes_ptr& slideN = notes_[i]; - - package::slide_content_ptr content = package::slide_content::create(); - - slideN->write_to(content->content()); - content->add_rels(slideN->Rels());//media & links rels - - output_document_->get_ppt_files().add_notes(content); - } - if (slideNotesMaster_) - { - package::slide_content_ptr content = package::slide_content::create(); - - slideNotesMaster_->write_to(content->content()); - content->add_rels(slideNotesMaster_->Rels());//media & links rels - - output_document_->get_ppt_files().add_notesMaster(content); - - CP_XML_WRITER(presentation_.slideNotesMastersData())//presentation.xml - { - CP_XML_NODE(L"p:notesMasterId") + for (size_t master_index = 0; master_index < masters.content.size(); master_index++) { - CP_XML_ATTR(L"r:id", slideNotesMaster_->rId()); + start_master(master_index); + + odf_reader::style_master_page* master = + root()->odf_context().pageLayoutContainer().master_page_by_name(masters.content[master_index].master_name); + + if (master) + { + master->pptx_convert(*this); + + if (!master_notes_ && master->presentation_notes_) + master_notes_ = master->presentation_notes_; + } + + + end_master(); + } + + if (master_notes_) + { + start_master_notes(); + master_notes_->pptx_convert(*this); + end_master_notes(); + } + process_masters_ = false; + get_text_context().set_process_layouts(false); + + } + + void pptx_conversion_context::process_styles() + { + + } + void pptx_conversion_context::process_theme(std::wstring name) + { + int current = themes_.size() + 1; + + if (name.empty()) + { + name = L"User Theme: " + std::to_wstring(current); + } + start_theme(name); + // + pptx_serialize_clrScheme(current_theme().clrSchemeData()); + pptx_serialize_fmtScheme(current_theme().fmtSchemeData()); + pptx_serialize_fontScheme(current_theme().fontSchemeData()); + // + end_theme(); + + } + void pptx_conversion_context::start_document() + { + odf_reader::odf_read_context& odfContext = root()->odf_context(); + std::vector instances; + + instances.push_back(odfContext.styleContainer().style_default_by_type(odf_types::style_family::Presentation)); + instances.push_back(odfContext.styleContainer().style_by_name(L"Default", odf_types::style_family::Presentation, false)); + + odf_reader::text_format_properties_ptr textFormatProperties = calc_text_properties_content(instances); + odf_reader::paragraph_format_properties parFormatProperties = calc_paragraph_properties_content(instances); + + process_masters_ = false; + } + + void pptx_conversion_context::end_document() + { + for (size_t i = 0; i < slideMasters_.size(); i++) + { + pptx_xml_slideMaster_ptr& slideM = slideMasters_[i]; + + package::slide_content_ptr content = package::slide_content::create(); + + slideM->write_to(content->content()); + content->add_rels(slideM->Rels());//media & links rels + + output_document_->get_ppt_files().add_slideMaster(content);//slideMaster.xml + + CP_XML_WRITER(presentation_.slideMastersData())//presentation.xml + { + CP_XML_NODE(L"p:sldMasterId") + { + CP_XML_ATTR(L"id", 0x80000000 + last_uniq_big_id++); + CP_XML_ATTR(L"r:id", slideM->rId()); + } + } + } + if (!slideMasters_.empty()) + presentation_.slidesProperties() << slideMasters_[0]->Sizes().str(); + + //////////////////////////////////////////////////////////////////////////////////////////////////// + for (size_t i = 0; i < slides_.size(); i++) + { + pptx_xml_slide_ptr& slide = slides_[i]; + + package::slide_content_ptr content = package::slide_content::create(); + + slide->write_to(content->content()); + content->add_rels(slide->Rels());//media & links rels + + output_document_->get_ppt_files().add_slide(content);//slide.xml + + CP_XML_WRITER(presentation_.slidesData())//presentation.xml + { + CP_XML_NODE(L"p:sldId") + { + CP_XML_ATTR(L"id", 0x100 + i); + CP_XML_ATTR(L"r:id", slide->rId()); + } + } + } + //---------------------------------------------------------------------------------- + for (size_t i = 0; i < slideLayouts_.size(); i++) + { + pptx_xml_slideLayout_ptr& slideL = slideLayouts_[i]; + + package::slide_content_ptr content = package::slide_content::create(); + + slideL->write_to(content->content()); + content->add_rels(slideL->Rels());//media & links rels + + output_document_->get_ppt_files().add_slideLayout(content);//slideMaster.xml + } + //---------------------------------------------------------------------------------- + for (size_t i = 0; i < notes_.size(); i++) + { + pptx_xml_slideNotes_ptr& slideN = notes_[i]; + + package::slide_content_ptr content = package::slide_content::create(); + + slideN->write_to(content->content()); + content->add_rels(slideN->Rels());//media & links rels + + output_document_->get_ppt_files().add_notes(content); + } + if (slideNotesMaster_) + { + package::slide_content_ptr content = package::slide_content::create(); + + slideNotesMaster_->write_to(content->content()); + content->add_rels(slideNotesMaster_->Rels());//media & links rels + + output_document_->get_ppt_files().add_notesMaster(content); + + CP_XML_WRITER(presentation_.slideNotesMastersData())//presentation.xml + { + CP_XML_NODE(L"p:notesMasterId") + { + CP_XML_ATTR(L"r:id", slideNotesMaster_->rId()); + } + } + } + //else + pptx_serialize_size(current_presentation().slidesNotesProperties(), 6858000, 9144000, L"p:notesSz"); + + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + + for (size_t i = 0; i < charts_.size(); i++) + { + package::chart_content_ptr content = package::chart_content::create(); + + charts_[i]->serialize(content->content()); + charts_[i]->dump_rels(content->get_rel_file()->get_rels()); + + output_document_->get_ppt_files().add_charts(content); + + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + for (size_t i = 0; i < themes_.size(); i++) + { + output_document_->get_ppt_files().add_theme(themes_[i]); + + } + package::ppt_comments_files_ptr comments = package::ppt_comments_files::create(comments_context_handle_.content()); + + output_document_->get_ppt_files().set_presentation(presentation_); + output_document_->get_ppt_files().set_comments(comments); + output_document_->get_ppt_files().set_authors_comments(authors_comments_); + output_document_->get_ppt_files().set_media(get_mediaitems()); + + output_document_->get_content_types_file().set_media(get_mediaitems()); + } + + void pptx_conversion_context::start_body() + { + + } + + void pptx_conversion_context::end_body() + { + } + pptx_xml_slideNotesMaster& pptx_conversion_context::current_notesMaster() + { + if (slideNotesMaster_) + { + return *slideNotesMaster_; + } + else + { + throw std::runtime_error("internal error"); } } - } - //else - pptx_serialize_size(current_presentation().slidesNotesProperties(), 6858000, 9144000, L"p:notesSz"); + pptx_xml_slideNotes& pptx_conversion_context::current_notes() + { + if (!notes_.empty()) + { + return *notes_.back().get(); + } + else + { + throw std::runtime_error("internal error"); + } + } + pptx_xml_slide& pptx_conversion_context::current_slide() + { + if (!slides_.empty()) + { + return *slides_.back().get(); + } + else + { + throw std::runtime_error("internal error"); + } + } + pptx_xml_slideLayout& pptx_conversion_context::current_layout() + { + if (!slideLayouts_.empty()) + { + return *slideLayouts_.back().get(); + } + else + { + throw std::runtime_error("internal error"); + } + } + pptx_xml_theme& pptx_conversion_context::current_theme() + { + if (!themes_.empty()) + { + return *themes_.back().get(); + } + else + { + throw std::runtime_error("internal error"); + } + } + pptx_xml_presentation& pptx_conversion_context::current_presentation() + { + return presentation_; + } -//////////////////////////////////////////////////////////////////////////////////////////////////////////// + oox_chart_context& pptx_conversion_context::current_chart() + { + if (!charts_.empty()) + { + return *charts_.back().get(); + } + else + { + throw std::runtime_error("internal error"); + } + } + pptx_xml_slideMaster& pptx_conversion_context::current_master() + { + if (!slideMasters_.empty()) + { + return *slideMasters_.back().get(); + } + else + { + throw std::runtime_error("internal error"); + } + } + void pptx_conversion_context::create_new_slide(std::wstring const& name) + { + pptx_xml_slide_ptr s = pptx_xml_slide::create(name, slides_.size() + 1); + slides_.push_back(s); + } + void pptx_conversion_context::create_new_slideNotes() + { + pptx_xml_slideNotes_ptr s = pptx_xml_slideNotes::create(notes_.size() + 1); + notes_.push_back(s); + } + void pptx_conversion_context::create_new_slideNotesMaster() + { + slideNotesMaster_ = pptx_xml_slideNotesMaster::create(); + } + void pptx_conversion_context::create_new_slideLayout(int id) + { + pptx_xml_slideLayout_ptr s = pptx_xml_slideLayout::create(id); + slideLayouts_.push_back(s); + } + void pptx_conversion_context::create_new_slideMaster(int id) + { + pptx_xml_slideMaster_ptr s = pptx_xml_slideMaster::create(id); + slideMasters_.push_back(s); + } + bool pptx_conversion_context::start_page(const std::wstring& pageName, const std::wstring& pageStyleName, + const std::wstring& pageLayoutName, + const std::wstring& pageMasterName) + { + create_new_slide(pageName); + get_slide_context().start_slide();//pageName, pageStyleName); - for (size_t i = 0; i < charts_.size(); i++) - { - package::chart_content_ptr content = package::chart_content::create(); + current_master_page_name_ = pageMasterName; + current_layout_page_name_ = pageLayoutName; - charts_[i]->serialize(content->content()); - charts_[i]->dump_rels(content->get_rel_file()->get_rels()); + //const std::wstring masterPageNameLayout = root()->odf_context().pageLayoutContainer().page_layout_name_by_style(current_master_page_name_); - output_document_->get_ppt_files().add_charts(content); - - } -//////////////////////////////////////////////////////////////////////////////////////////////////////////// - for (size_t i=0; i < themes_.size(); i++) - { - output_document_->get_ppt_files().add_theme(themes_[i]); - - } - package::ppt_comments_files_ptr comments = package::ppt_comments_files::create(comments_context_handle_.content()); - - output_document_->get_ppt_files().set_presentation (presentation_); - output_document_->get_ppt_files().set_comments (comments); - output_document_->get_ppt_files().set_authors_comments (authors_comments_); - output_document_->get_ppt_files().set_media (get_mediaitems()); + std::pair layout_id = + root()->odf_context().styleContainer().presentation_layouts().add_or_find(pageLayoutName, pageMasterName); - output_document_->get_content_types_file().set_media(get_mediaitems()); -} + current_slide().Rels().add(relationship(layout_id.second, L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout", + std::wstring(L"../slideLayouts/slideLayout") + std::to_wstring(layout_id.first) + L".xml")); -void pptx_conversion_context::start_body() -{} + return true; + } -void pptx_conversion_context::end_body() -{} -pptx_xml_slideNotesMaster & pptx_conversion_context::current_notesMaster() -{ - if (slideNotesMaster_) - { - return *slideNotesMaster_; - } - else - { - throw std::runtime_error("internal error"); - } -} -pptx_xml_slideNotes & pptx_conversion_context::current_notes() -{ - if (!notes_.empty()) - { - return *notes_.back().get(); - } - else - { - throw std::runtime_error("internal error"); - } -} -pptx_xml_slide & pptx_conversion_context::current_slide() -{ - if (!slides_.empty()) - { - return *slides_.back().get(); - } - else - { - throw std::runtime_error("internal error"); - } -} -pptx_xml_slideLayout & pptx_conversion_context::current_layout() -{ - if (!slideLayouts_.empty()) - { - return *slideLayouts_.back().get(); - } - else - { - throw std::runtime_error("internal error"); - } -} -pptx_xml_theme & pptx_conversion_context::current_theme() -{ - if (!themes_.empty()) - { - return *themes_.back().get(); - } - else - { - throw std::runtime_error("internal error"); - } -} -pptx_xml_presentation & pptx_conversion_context::current_presentation() -{ - return presentation_; -} + bool pptx_conversion_context::start_layout(int layout_index) + { + if (layout_index >= 0) + { + odf_reader::presentation_layouts_instance& layouts = root()->odf_context().styleContainer().presentation_layouts(); -oox_chart_context & pptx_conversion_context::current_chart() -{ - if (!charts_.empty()) - { - return *charts_.back().get(); - } - else - { - throw std::runtime_error("internal error"); - } -} -pptx_xml_slideMaster & pptx_conversion_context::current_master() -{ - if (!slideMasters_.empty()) - { - return *slideMasters_.back().get(); - } - else - { - throw std::runtime_error("internal error"); - } -} -void pptx_conversion_context::create_new_slide(std::wstring const & name) -{ - pptx_xml_slide_ptr s = pptx_xml_slide::create(name,slides_.size() + 1); - slides_.push_back(s); -} -void pptx_conversion_context::create_new_slideNotes() -{ - pptx_xml_slideNotes_ptr s = pptx_xml_slideNotes::create( notes_.size() + 1); - notes_.push_back(s); -} -void pptx_conversion_context::create_new_slideNotesMaster() -{ - slideNotesMaster_ = pptx_xml_slideNotesMaster::create(); -} -void pptx_conversion_context::create_new_slideLayout(int id) -{ - pptx_xml_slideLayout_ptr s = pptx_xml_slideLayout::create(id); - slideLayouts_.push_back(s); -} -void pptx_conversion_context::create_new_slideMaster(int id) -{ - pptx_xml_slideMaster_ptr s = pptx_xml_slideMaster::create(id); - slideMasters_.push_back(s); -} -bool pptx_conversion_context::start_page(const std::wstring & pageName, const std::wstring & pageStyleName, - const std::wstring & pageLayoutName, - const std::wstring & pageMasterName) -{ - create_new_slide(pageName); - get_slide_context().start_slide();//pageName, pageStyleName); + create_new_slideLayout(layouts.content[layout_index].Id); - current_master_page_name_ = pageMasterName; - current_layout_page_name_ = pageLayoutName; - - //const std::wstring masterPageNameLayout = root()->odf_context().pageLayoutContainer().page_layout_name_by_style(current_master_page_name_); + get_slide_context().start_slide();//layouts.content[layout_index].layout_name, L"");//????? - std::pair layout_id = - root()->odf_context().styleContainer().presentation_layouts().add_or_find(pageLayoutName,pageMasterName); + current_master_page_name_ = layouts.content[layout_index].master_name; + current_layout_page_name_ = L""; - current_slide().Rels().add(relationship(layout_id.second, L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout", - std::wstring(L"../slideLayouts/slideLayout") + std::to_wstring(layout_id.first) + L".xml")); + std::pair master_id = //std::pair(1, L"smId1"); + root()->odf_context().styleContainer().presentation_masters().add_or_find(layouts.content[layout_index].master_name); - return true; -} + root()->odf_context().styleContainer().presentation_masters().add_layout_to(layouts.content[layout_index].master_name, layouts.content[layout_index]); -bool pptx_conversion_context::start_layout(int layout_index) -{ - if (layout_index >=0) - { - odf_reader::presentation_layouts_instance & layouts = root()->odf_context().styleContainer().presentation_layouts(); + current_layout().Rels().add(relationship(L"smId1"/*master_id.second*/, L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster", + std::wstring(L"../slideMasters/slideMaster") + std::to_wstring(master_id.first) + L".xml")); - create_new_slideLayout(layouts.content[layout_index].Id); - - get_slide_context().start_slide();//layouts.content[layout_index].layout_name, L"");//????? + // + } + else//общий шаблон (насильно пропишем к темам несоответствующие шалоны) + { + } - current_master_page_name_ = layouts.content[layout_index].master_name; - current_layout_page_name_ = L""; - - std::pair master_id = //std::pair(1,L"smId1"); - root()->odf_context().styleContainer().presentation_masters().add_or_find(layouts.content[layout_index].master_name); + //layout type - root()->odf_context().styleContainer().presentation_masters().add_layout_to(layouts.content[layout_index].master_name,layouts.content[layout_index]); + // + //1375 + //1376 + //1377 + //1378 + //1379 + //1380 + //1381 + //1382 + //1383 + //1384 + //1385 + //1386 + //1387 + //1388 + //1389 + //1390 + //1391 + //1392 + //1393 + //1394 + //1395 + //1396 + //1397 + //1398 + //1399 + //1400 + //1401 + //1402 + //1403 + //1404 + //1405 ---------------------------------- !!!!!!!!!!!!! + //1406 + //1407 + //1408 + //1409 - current_layout().Rels().add(relationship(L"smId1"/*master_id.second*/, L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster", - std::wstring(L"../slideMasters/slideMaster") + std::to_wstring(master_id.first) + L".xml")); + return true; + } + bool pptx_conversion_context::start_master(int master_index) + { + odf_reader::presentation_masters_instance& masters = root()->odf_context().styleContainer().presentation_masters(); - // - } - else//общий шаблон (насильно пропишем к темам несоответствующие шалоны) - { - } + create_new_slideMaster(masters.content[master_index].Id); -//layout type + get_slide_context().start_slide(); -// -//1375 -//1376 -//1377 -//1378 -//1379 -//1380 -//1381 -//1382 -//1383 -//1384 -//1385 -//1386 -//1387 -//1388 -//1389 -//1390 -//1391 -//1392 -//1393 -//1394 -//1395 -//1396 -//1397 -//1398 -//1399 -//1400 -//1401 -//1402 -//1403 -//1404 -//1405 ---------------------------------- !!!!!!!!!!!!! -//1406 -//1407 -//1408 -//1409 - - return true; -} -bool pptx_conversion_context::start_master(int master_index) -{ - odf_reader::presentation_masters_instance & masters = root()->odf_context().styleContainer().presentation_masters(); + current_master_page_name_ = L""; + current_layout_page_name_ = L""; - create_new_slideMaster(masters.content[master_index].Id); - - get_slide_context().start_slide(); + process_theme(masters.content[master_index].master_name);//add default theme - одинаковые но под разными именами + current_master().add_theme(current_theme().id(), L"tId1"); - current_master_page_name_ = L""; - current_layout_page_name_ = L""; - - process_theme(masters.content[master_index].master_name);//add default theme - одинаковые но под разными именами - current_master().add_theme(current_theme().id(), L"tId1"); + for (size_t i = 0; i < masters.content[master_index].layouts.size(); i++) + { + current_master().add_layout(masters.content[master_index].layouts[i].Id, masters.content[master_index].layouts[i].rId, 0x80000000 + last_uniq_big_id++); + } - for (size_t i = 0; i < masters.content[master_index].layouts.size(); i++) - { - current_master().add_layout(masters.content[master_index].layouts[i].Id, masters.content[master_index].layouts[i].rId, 0x80000000 + last_uniq_big_id++); - } + //---------------------------------------------------------------------------------- + //размеры страниц в презентации + const std::wstring pageProperties = root()->odf_context().pageLayoutContainer().page_layout_name_by_style(masters.content[master_index].master_name); -//---------------------------------------------------------------------------------- -//размеры страниц в презентации - const std::wstring pageProperties = root()->odf_context().pageLayoutContainer().page_layout_name_by_style(masters.content[master_index].master_name); + odf_reader::page_layout_instance* pages_layouts = root()->odf_context().pageLayoutContainer().page_layout_by_name(pageProperties); - odf_reader::page_layout_instance *pages_layouts = root()->odf_context().pageLayoutContainer().page_layout_by_name(pageProperties); - - if (pages_layouts) - pages_layouts->pptx_serialize(current_master().Sizes(), *this); + if (pages_layouts) + pages_layouts->pptx_serialize(current_master().Sizes(), *this); - return true; -} -void pptx_conversion_context::end_page() -{ - if (!get_comments_context().empty()) - { - std::wstringstream strm; - get_comments_context().serialize(strm); - - const std::pair commentsName = - comments_context_handle_.add_comments_xml(strm.str(), get_comments_context().get_comments() ); + return true; + } + void pptx_conversion_context::end_page() + { + if (!get_comments_context().empty()) + { + std::wstringstream strm; + get_comments_context().serialize(strm); - get_slide_context().add_rels(false, commentsName.second, L"../comments/" + commentsName.first, typeComment); - } + const std::pair commentsName = + comments_context_handle_.add_comments_xml(strm.str(), get_comments_context().get_comments()); - get_slide_context().serialize_background(current_slide().Background()); - get_slide_context().serialize_objects (current_slide().Data()); - get_slide_context().serialize_animations(current_slide().Timing()); + get_slide_context().add_rels(false, commentsName.second, L"../comments/" + commentsName.first, typeComment); + } - { - // NOTE: При использовании operator<< потока буст пушит туда лишний пробел перед значением. - // С этим пробелом наш редактор onlyoffice на распознает значение. - // Example: - // ppt_y - // ppt_y - // TODO: Figure out how to push value without redundant space character - current_slide().remove_timing_redundant_space(); - } - - get_slide_context().dump_rels(current_slide().Rels());//hyperlinks, mediaitems, ... + get_slide_context().serialize_background(current_slide().Background()); + get_slide_context().serialize_objects(current_slide().Data()); + get_slide_context().serialize_animations(current_slide().Timing()); - get_slide_context().end_slide(); -} -bool pptx_conversion_context::start_page_notes() -{ - create_new_slideNotes( ); + { + // NOTE: При использовании operator<< потока буст пушит туда лишний пробел перед значением. + // С этим пробелом наш редактор onlyoffice на распознает значение. + // Example: + // ppt_y + // ppt_y + // TODO: Figure out how to push value without redundant space character + current_slide().remove_timing_redundant_space(); + } - current_slide().Rels().add(relationship(notes_.back()->rId(), L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide", - L"../notesSlides/notesSlide" + std::to_wstring(notes_.size()) + L".xml")); + get_slide_context().dump_rels(current_slide().Rels());//hyperlinks, mediaitems, ... - get_slide_context().start_slide(); - - current_notes().Rels().add(relationship(L"nId1", L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide", - L"../slides/slide" + std::to_wstring(slides_.size()) + L".xml")); - - return true; -} + get_slide_context().end_slide(); + } + bool pptx_conversion_context::start_page_notes() + { + create_new_slideNotes(); -void pptx_conversion_context::end_page_notes() -{ - get_slide_context().serialize_background(current_notes().Background()); - get_slide_context().serialize_objects(current_notes().Data()); + current_slide().Rels().add(relationship(notes_.back()->rId(), L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide", + L"../notesSlides/notesSlide" + std::to_wstring(notes_.size()) + L".xml")); - get_slide_context().dump_rels(current_notes().Rels());//hyperlinks, mediaitems, ... + get_slide_context().start_slide(); - get_slide_context().end_slide(); -} -bool pptx_conversion_context::start_master_notes() -{ - create_new_slideNotesMaster( ); - - get_slide_context().start_slide(); + current_notes().Rels().add(relationship(L"nId1", L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide", + L"../slides/slide" + std::to_wstring(slides_.size()) + L".xml")); - process_theme(L"");//add default theme - одинаковые но под разными именами - current_notesMaster().add_theme(current_theme().id(), L"tId1"); + return true; + } - get_slide_context().start_slide(); - return true; -} + void pptx_conversion_context::end_page_notes() + { + get_slide_context().serialize_background(current_notes().Background()); + get_slide_context().serialize_objects(current_notes().Data()); -void pptx_conversion_context::end_master_notes() -{ - get_slide_context().serialize_background(current_notesMaster().Background()); - get_slide_context().serialize_objects(current_notesMaster().Data()); + get_slide_context().dump_rels(current_notes().Rels());//hyperlinks, mediaitems, ... - get_slide_context().dump_rels(current_notesMaster().Rels());//hyperlinks, mediaitems, ... + get_slide_context().end_slide(); + } + bool pptx_conversion_context::start_master_notes() + { + create_new_slideNotesMaster(); - get_slide_context().end_slide(); - - for (size_t i = 0; i < notes_.size(); i++) - { - notes_[i]->Rels().add(relationship(L"nmId1", - L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesMaster", - L"../notesMasters/notesMaster1.xml")); + get_slide_context().start_slide(); + + process_theme(L"");//add default theme - одинаковые но под разными именами + current_notesMaster().add_theme(current_theme().id(), L"tId1"); + + get_slide_context().start_slide(); + return true; + } + + void pptx_conversion_context::end_master_notes() + { + get_slide_context().serialize_background(current_notesMaster().Background()); + get_slide_context().serialize_objects(current_notesMaster().Data()); + + get_slide_context().dump_rels(current_notesMaster().Rels());//hyperlinks, mediaitems, ... + + get_slide_context().end_slide(); + + for (size_t i = 0; i < notes_.size(); i++) + { + notes_[i]->Rels().add(relationship(L"nmId1", + L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesMaster", + L"../notesMasters/notesMaster1.xml")); + } + } + void pptx_conversion_context::end_layout() + { + get_slide_context().serialize_objects(current_layout().Data()); + + get_slide_context().dump_rels(current_layout().Rels());//hyperlinks, mediaitems, ... + + get_slide_context().end_slide(); + } + + std::pair pptx_conversion_context::add_author_comments(std::wstring author) + { + if (!authors_comments_) + { + authors_comments_ = pptx_xml_authors_comments::create(); + if (!authors_comments_)return std::pair(-1, -1); + } + + return authors_comments_->add_or_find(author); + } + + void pptx_conversion_context::end_master() + { + get_slide_context().serialize_background(current_master().Background(), true); + get_slide_context().serialize_objects(current_master().Data()); + get_slide_context().serialize_HeaderFooter(current_master().DataExtra()); + + get_slide_context().dump_rels(current_master().Rels());//hyperlinks, mediaitems, ... + + get_slide_context().end_slide(); + } + void pptx_conversion_context::start_theme(std::wstring& name) + { + themes_.push_back(pptx_xml_theme::create(name, themes_.size() + 1)); + } + void pptx_conversion_context::end_theme() + { + } + void pptx_conversion_context::start_office_presentation() + { + } + + void pptx_conversion_context::end_office_presentation() + { + } + void pptx_conversion_context::start_chart(std::wstring name) + { + charts_.push_back(oox_chart_context_ptr(new oox_chart_context(get_mediaitems(), name))); + //добавляем новую форму для диаграммы + //в ней будет информационная часть - и она пишется каждый раз в свою xml (их - по числу диаграмм) + //этот контекст нужно передавать в файл + + } + void pptx_conversion_context::end_chart() + { + //current_chart().set_drawing_link(current_sheet().get_drawing_link()); + //излишняя инфа + } + void pptx_conversion_context::add_jsaProject(const std::string& content) + { + if (content.empty()) return; + + output_document_->get_ppt_files().add_jsaProject(content); + output_document_->get_content_types_file().add_or_find_default(L"bin"); + } } } -void pptx_conversion_context::end_layout() -{ - get_slide_context().serialize_objects(current_layout().Data()); - - get_slide_context().dump_rels(current_layout().Rels());//hyperlinks, mediaitems, ... - - get_slide_context().end_slide(); -} - -std::pair pptx_conversion_context::add_author_comments(std::wstring author) -{ - if (!authors_comments_) - { - authors_comments_ = pptx_xml_authors_comments::create(); - if (!authors_comments_)return std::pair(-1,-1); - } - - return authors_comments_->add_or_find(author); -} - -void pptx_conversion_context::end_master() -{ - get_slide_context().serialize_background (current_master().Background(),true); - get_slide_context().serialize_objects (current_master().Data()); - get_slide_context().serialize_HeaderFooter (current_master().DataExtra()); - - get_slide_context().dump_rels(current_master().Rels());//hyperlinks, mediaitems, ... - - get_slide_context().end_slide(); -} -void pptx_conversion_context::start_theme(std::wstring & name) -{ - themes_.push_back(pptx_xml_theme::create(name,themes_.size()+1)); -} -void pptx_conversion_context::end_theme() -{ -} -void pptx_conversion_context::start_office_presentation() -{ -} - -void pptx_conversion_context::end_office_presentation() -{ -} -void pptx_conversion_context::start_chart(std::wstring name) -{ - charts_.push_back(oox_chart_context_ptr(new oox_chart_context(get_mediaitems(), name))); - //добавляем новую форму для диаграммы - //в ней будет информационная часть - и она пишется каждый раз в свою xml (их - по числу диаграмм) - //этот контекст нужно передавать в файл - -} -void pptx_conversion_context::end_chart() -{ - //current_chart().set_drawing_link(current_sheet().get_drawing_link()); - //излишняя инфа -} -void pptx_conversion_context::add_jsaProject(const std::string &content) -{ - if (content.empty()) return; - - output_document_->get_ppt_files().add_jsaProject(content); - output_document_->get_content_types_file().add_or_find_default(L"bin"); -} -} -} diff --git a/OdfFile/Reader/Converter/pptx_drawing.cpp b/OdfFile/Reader/Converter/pptx_drawing.cpp index 04b5833624..757b27653d 100644 --- a/OdfFile/Reader/Converter/pptx_drawing.cpp +++ b/OdfFile/Reader/Converter/pptx_drawing.cpp @@ -227,7 +227,7 @@ void pptx_serialize_shape(std::wostream & strm, _pptx_drawing & val) { CP_XML_NODE(L"p:ph") { - CP_XML_ATTR(L"type",val.place_holder_type_); + CP_XML_ATTR(L"type", val.place_holder_type_); if (val.place_holder_idx_ > 0) CP_XML_ATTR(L"idx", val.place_holder_idx_); if (val.place_holder_type_ == L"dt") { CP_XML_ATTR(L"sz", L"half"); } @@ -242,19 +242,19 @@ void pptx_serialize_shape(std::wostream & strm, _pptx_drawing & val) _CP_OPT(bool) bNoRect; odf_reader::GetProperty(val.additional,L"no_rect",bNoRect); + if (val.cx != 0 || val.cy != 0) //layout + { + val.serialize_xfrm(CP_XML_STREAM(), L"a", true); + } if (!bNoRect) - { - if (val.cx != 0 || val.cy != 0) //layout - { - val.serialize_xfrm(CP_XML_STREAM(), L"a", true); - } + { val.serialize_shape(CP_XML_STREAM()); oox_serialize_ln(CP_XML_STREAM(), val.additional); oox_serialize_effects(CP_XML_STREAM(), val.additional); } } - pptx_serialize_text(CP_XML_STREAM(), val); + pptx_serialize_text(CP_XML_STREAM(), val); } } // CP_XML_WRITER } @@ -295,7 +295,7 @@ void pptx_serialize_connector(std::wostream & strm, _pptx_drawing & val) } CP_XML_NODE(L"p:nvPr") { - if (val.place_holder_type_.length()>0) + if (false == val.place_holder_type_.empty()) { CP_XML_NODE(L"p:ph") { @@ -326,7 +326,7 @@ void pptx_serialize_connector(std::wostream & strm, _pptx_drawing & val) oox_serialize_effects(CP_XML_STREAM(), val.additional); } } - pptx_serialize_text(CP_XML_STREAM(), val); + pptx_serialize_text(CP_XML_STREAM(), val); } } // CP_XML_WRITER } diff --git a/OdfFile/Reader/Converter/pptx_slide_context.cpp b/OdfFile/Reader/Converter/pptx_slide_context.cpp index a909e2a884..3b69adf2fb 100644 --- a/OdfFile/Reader/Converter/pptx_slide_context.cpp +++ b/OdfFile/Reader/Converter/pptx_slide_context.cpp @@ -322,11 +322,11 @@ void pptx_slide_context::set_placeHolder_type(std::wstring typeHolder) if (typeHolder == L"dt") impl_->date_time = true; if (typeHolder == L"sldNum")impl_->slideNum = true; - impl_->object_description_.additional_.push_back(odf_reader::_property(L"PlaceHolderType",typeHolder)); + impl_->object_description_.additional_.push_back(odf_reader::_property(L"PlaceHolderType", typeHolder)); } void pptx_slide_context::set_placeHolder_idx(int idx) { - impl_->object_description_.additional_.push_back(odf_reader::_property(L"PlaceHolderIdx",idx)); + impl_->object_description_.additional_.push_back(odf_reader::_property(L"PlaceHolderIdx", idx)); } void pptx_slide_context::set_rect(double width_pt, double height_pt, double x_pt, double y_pt) @@ -1012,7 +1012,7 @@ void pptx_slide_context::serialize_objects(std::wostream & strm) } } } - //process_drawings(); + process_drawings(); impl_->get_drawings()->serialize(strm); } diff --git a/OdfFile/Reader/Converter/pptx_text_context.cpp b/OdfFile/Reader/Converter/pptx_text_context.cpp index c09736a311..0bfc224aea 100644 --- a/OdfFile/Reader/Converter/pptx_text_context.cpp +++ b/OdfFile/Reader/Converter/pptx_text_context.cpp @@ -452,7 +452,7 @@ std::wstring pptx_text_context::Impl::dump_paragraph(/*bool last*/) std::wstring str_run = run_.str(); - if (str_run.length() > 0 || paragraph_style_name_.length() > 0) + if (false == str_run.empty() || false == paragraph_style_name_.empty() || (false == base_style_name_.empty() && process_layouts_)) { CP_XML_WRITER(paragraph_) { diff --git a/OdfFile/Reader/Format/draw_frame_pptx.cpp b/OdfFile/Reader/Format/draw_frame_pptx.cpp index bb1e0488ee..55df515d82 100644 --- a/OdfFile/Reader/Format/draw_frame_pptx.cpp +++ b/OdfFile/Reader/Format/draw_frame_pptx.cpp @@ -77,7 +77,7 @@ void draw_g::pptx_convert(oox::pptx_conversion_context & Context) } void draw_frame::pptx_convert_placeHolder(oox::pptx_conversion_context & Context) { - Context.get_slide_context().set_property(_property(L"no_rect",true)); + Context.get_slide_context().set_property(_property(L"no_rect", true)); pptx_convert(Context); } void draw_frame::pptx_convert(oox::pptx_conversion_context & Context) diff --git a/OdfFile/Reader/Format/draw_page.cpp b/OdfFile/Reader/Format/draw_page.cpp index 7b5869fe29..4e40193f40 100644 --- a/OdfFile/Reader/Format/draw_page.cpp +++ b/OdfFile/Reader/Format/draw_page.cpp @@ -88,9 +88,9 @@ void draw_page::pptx_convert_placeHolder(oox::pptx_conversion_context & Context, office_element_ptr elm = Context.root()->odf_context().drawStyles().find_by_style_name(styleName); //todooo если это элемент datatime -нужно вытащить формат поля - if (!elm)return; + if (!elm) return; - int index=-1; + int index = -1; const std::wstring masterName = attlist_.master_page_name_.get_value_or(L""); style_master_page * master = Context.root()->odf_context().pageLayoutContainer().master_page_by_name(masterName); @@ -98,7 +98,6 @@ void draw_page::pptx_convert_placeHolder(oox::pptx_conversion_context & Context, if (master) index = master->find_placeHolderIndex(PresentationClass, Context.last_idx_placeHolder); - Context.get_slide_context().start_shape(1); Context.get_slide_context().set_placeHolder_type(presentation_class(PresentationClass).get_type_ms()); Context.get_slide_context().set_placeHolder_idx(index); @@ -114,11 +113,11 @@ void draw_page::pptx_convert_placeHolder(oox::pptx_conversion_context & Context, std::wstring text_content_ = Context.get_text_context().end_object(); - if (text_content_.length()>0) + if (false == text_content_.empty()) { - Context.get_slide_context().set_property(_property(L"text-content",text_content_)); + Context.get_slide_context().set_property(_property(L"text-content", text_content_)); } - Context.get_slide_context().set_property(_property(L"no_rect",true)); + Context.get_slide_context().set_property(_property(L"no_rect", true)); Context.get_slide_context().end_shape(); } @@ -132,11 +131,11 @@ void draw_page::pptx_convert(oox::pptx_conversion_context & Context) _CP_LOG << L"[info][pptx] process page(slide) \"" << pageName /*L"" */<< L"\"" << std::endl; - Context.start_page(pageName, pageStyleName, layoutName,masterName); + Context.start_page(pageName, pageStyleName, layoutName, masterName); if (attlist_.draw_style_name_) { - style_instance * style_inst = Context.root()->odf_context().styleContainer().style_by_name(pageStyleName,style_family::DrawingPage,false); + style_instance * style_inst = Context.root()->odf_context().styleContainer().style_by_name(pageStyleName,style_family::DrawingPage, false); if ((style_inst) && (style_inst->content())) { @@ -307,11 +306,11 @@ void presentation_notes::pptx_convert_placeHolder(oox::pptx_conversion_context & std::wstring text_content_ = Context.get_text_context().end_object(); - if (text_content_.length()>0) + if (false == text_content_.empty()) { - Context.get_slide_context().set_property(_property(L"text-content",text_content_)); + Context.get_slide_context().set_property(_property(L"text-content", text_content_)); } - Context.get_slide_context().set_property(_property(L"no_rect",true)); + Context.get_slide_context().set_property(_property(L"no_rect", true)); Context.get_slide_context().end_shape(); } diff --git a/OdfFile/Reader/Format/odfcontext.cpp b/OdfFile/Reader/Format/odfcontext.cpp index 45cfde2b04..15c23001cc 100644 --- a/OdfFile/Reader/Format/odfcontext.cpp +++ b/OdfFile/Reader/Format/odfcontext.cpp @@ -32,14 +32,14 @@ #include "odfcontext.h" -namespace cpdoccore { +namespace cpdoccore { using namespace odf_types; - - std::string DecodeBase64(const std::wstring & value1) + + std::string DecodeBase64(const std::wstring& value1) { int nLength = 0; - unsigned char *pData = NULL; + unsigned char* pData = NULL; std::string result; std::string value(value1.begin(), value1.end()); @@ -48,641 +48,624 @@ namespace cpdoccore { if (pData) { result = std::string((char*)pData, nLength); - delete []pData; pData = NULL; + delete[]pData; pData = NULL; } return result; } -namespace odf_reader { + namespace odf_reader { -style_instance::style_instance( - styles_container *Container, - const std::wstring &Name, - const std::wstring &DisplayName, - style_family::type Type, - style_content *Content, - bool IsAutomatic, - bool IsDefault, - const std::wstring & ParentStyleName, - const std::wstring & NextStyleName, - const std::wstring & DataStyleName, - const std::wstring & PercentageDataStyleName, - const std::wstring & StyleClass, - _CP_OPT(std::wstring) ListStyleName, - _CP_OPT(int) ListLevel, - _CP_OPT(int) OutlineLevel - ) : - container_ (Container), - name_ (Name), - display_name_ (DisplayName), - style_type_ (Type), - content_ (Content), - is_automatic_ (IsAutomatic), - is_default_ (IsDefault), - next_name_ (NextStyleName), - style_class_ (StyleClass), - next_ (Container->style_by_name(NextStyleName, style_type_, false)), - data_style_name_(DataStyleName), - percentage_data_style_name_(PercentageDataStyleName), - list_style_name_(ListStyleName), - list_level_ (ListLevel), - outline_level_ (OutlineLevel) -{ - parent_name_ = ParentStyleName; - if (parent_name_ == L"Textformatvorlage")//http://ask.libreoffice.org/en/question/35136/textformatvorlage-style/ - { - parent_name_ = L"Standard"; - } - parent_ = Container->style_by_name(parent_name_, style_type_, false); -} - -style_instance * styles_container::hyperlink_style() -{ - if (hyperlink_style_pos_ > 0 && hyperlink_style_pos_ < (int)instances_.size()) - return instances_[hyperlink_style_pos_].get(); - else - return NULL; -} - -void styles_container::add_style( const std::wstring & Name, - const std::wstring & DisplayName, - style_content * Content, - bool IsAutomatic, - bool IsDefault, - const std::wstring & ParentStyleName_, - const std::wstring & NextStyleName, - const std::wstring & DataStyleName, - const std::wstring & PercentageDataStyleName, - const std::wstring & StyleClass, - _CP_OPT(std::wstring) ListStyleName, - _CP_OPT(int) ListLevel, - _CP_OPT(int) OutlineLevel) -{ - std::wstring ParentStyleName = ParentStyleName_; - - style_family::type Type = Content ? Content->style_family_.get_type() : style_family::None; - - if (Name == ParentStyleName) - { - ParentStyleName = L"";//иначе в коде возможно зацикливание. - } - style_instance_ptr newStyle = style_instance_ptr( new style_instance(this, Name, DisplayName, Type, Content, IsAutomatic, IsDefault, - ParentStyleName, NextStyleName, DataStyleName, PercentageDataStyleName, StyleClass, ListStyleName, ListLevel, OutlineLevel)); - - instances_.push_back(newStyle); - int pos = static_cast(instances_.size() - 1); - - if (!Name.empty()) - { - std::wstring n = Name + L":" + boost::lexical_cast( style_family(Type) ); - map_[n] = pos; - - // TODO: как правильно?? - std::wstring lName = XmlUtils::GetLower(Name); - //if ( boost::algorithm::contains(lName, L"internet_20_link") ) - if (lName == L"internet_20_link")///??????????????? - hyperlink_style_pos_ = pos; - } - - if (!DisplayName.empty()) - { - std::wstring n = DisplayName + L":" + boost::lexical_cast( style_family(Type) ); - map2_[n] = pos; - } - - if (IsDefault) - default_map_[Type] = pos; - -} - -const std::wstring & style_instance::name() const -{ - return name_; -} -const std::wstring & style_instance::display_name() const -{ - return display_name_; -} -style_family::type style_instance::type() const -{ - return style_type_; -} - -style_content * style_instance::content() const -{ - return content_; -} - -style_instance * style_instance::parent() const -{ - if (parent_) - return parent_; - else if (container_) - parent_ = container_->style_by_name(parent_name_, type(), false); - - return parent_; -} - -const std::wstring & style_instance::parent_name() const -{ - return parent_name_; -} - -style_instance * style_instance::next() const -{ - if (next_) - return next_; - else if (container_ && next_name_.empty() == false) - next_ = container_->style_by_name(next_name_, type(), false); - - return next_; -} - -const std::wstring & style_instance::next_name() const -{ - return next_name_; -} - -bool style_instance::is_automatic() const -{ - return is_automatic_; -} - -bool style_instance::is_default() const -{ - return is_default_; -} -const std::wstring & style_instance::percentage_data_style_name() const -{ - return percentage_data_style_name_; -} -const std::wstring & style_instance::data_style_name() const -{ - return data_style_name_; -} -_CP_OPT(std::wstring) style_instance::list_style_name() const -{ - return list_style_name_; -} -const std::wstring & style_instance::style_class() const -{ - return style_class_; -} -_CP_OPT(int) style_instance::list_level() const -{ - return list_level_; -} -_CP_OPT(int) style_instance::outline_level() const -{ - return outline_level_; -} - -style_instance * styles_container::style_by_name(const std::wstring & Name, style_family::type Type, bool object_in_styles) const -{ - std::wstring n = L""; - if (object_in_styles) n = L"common:"; - n = n + Name + L":" + boost::lexical_cast( style_family(Type) ); - - map_wstring_int_t::const_iterator res = map_.find(n); - - if (res != map_.end()) - { - int index = res->second; - return instances_[index].get(); - } - else if (object_in_styles) - { - //try automatic - n = Name + L":" + boost::lexical_cast( style_family(Type) ); - - map_wstring_int_t::const_iterator res = map_.find(n); - - if (res != map_.end()) + style_instance::style_instance( + styles_container* Container, + const std::wstring& Name, + const std::wstring& DisplayName, + style_family::type Type, + style_content* Content, + bool IsAutomatic, + bool IsDefault, + const std::wstring& ParentStyleName, + const std::wstring& NextStyleName, + const std::wstring& DataStyleName, + const std::wstring& PercentageDataStyleName, + const std::wstring& StyleClass, + _CP_OPT(std::wstring) ListStyleName, + _CP_OPT(int) ListLevel, + _CP_OPT(int) OutlineLevel + ) : + container_(Container), + name_(Name), + display_name_(DisplayName), + style_type_(Type), + content_(Content), + is_automatic_(IsAutomatic), + is_default_(IsDefault), + next_name_(NextStyleName), + style_class_(StyleClass), + next_(Container->style_by_name(NextStyleName, style_type_, false)), + data_style_name_(DataStyleName), + percentage_data_style_name_(PercentageDataStyleName), + list_style_name_(ListStyleName), + list_level_(ListLevel), + outline_level_(OutlineLevel) { - int index = res->second; - return instances_[index].get(); + parent_name_ = ParentStyleName; + if (parent_name_ == L"Textformatvorlage")//http://ask.libreoffice.org/en/question/35136/textformatvorlage-style/ + { + parent_name_ = L"Standard"; + } + parent_ = Container->style_by_name(parent_name_, style_type_, false); } - } - return NULL; -} -style_instance * styles_container::style_by_display_name(const std::wstring & Name, style_family::type Type, bool object_in_styles) const -{ - std::wstring n = L""; - if (object_in_styles) n = L"common:"; - n = n + Name + L":" + boost::lexical_cast( style_family(Type) ); - - map_wstring_int_t::const_iterator res = map2_.find(n); - - if (res != map2_.end()) - { - int index = res->second; - return instances_[index].get(); - } - else - return NULL; -} -void styles_container::add_master_page_name(const std::wstring & StyleName, const std::wstring & MasterPageName) -{ - master_page_name_[StyleName] = MasterPageName; -} -std::pair presentation_layouts_instance::add_or_find(const std::wstring & layout_name,const std::wstring & master_name) -{ - bool find = false; - size_t index =0; - - for (index = 0; index < content.size(); index++) - { - if (content[index].layout_name == layout_name && content[index].master_name == master_name) + style_instance* styles_container::hyperlink_style() { - find = true; - break; + if (hyperlink_style_pos_ > 0 && hyperlink_style_pos_ < (int)instances_.size()) + return instances_[hyperlink_style_pos_].get(); + else + return NULL; } - } - if (!find) - { - presentation_layouts_instance::_layout item; - item.layout_name = layout_name; - item.master_name = master_name; - item.Id = content.size() +1; - item.rId = std::wstring(L"lrId") + std::to_wstring(item.Id); - - content.push_back(item); - index = content.size()-1; - } - return std::pair(content[index].Id,content[index].rId); -} - -std::pair presentation_masters_instance::add_or_find(const std::wstring & master_name) -{ - bool find = false; - size_t index =0; - for (index = 0; index < content.size(); index++) - { - if (content[index].master_name == master_name) + void styles_container::add_style(const std::wstring& Name, + const std::wstring& DisplayName, + style_content* Content, + bool IsAutomatic, + bool IsDefault, + const std::wstring& ParentStyleName_, + const std::wstring& NextStyleName, + const std::wstring& DataStyleName, + const std::wstring& PercentageDataStyleName, + const std::wstring& StyleClass, + _CP_OPT(std::wstring) ListStyleName, + _CP_OPT(int) ListLevel, + _CP_OPT(int) OutlineLevel) { - find = true; - break; + std::wstring ParentStyleName = ParentStyleName_; + + style_family::type Type = Content ? Content->style_family_.get_type() : style_family::None; + + if (Name == ParentStyleName) + { + ParentStyleName = L"";//иначе в коде возможно зацикливание. + } + style_instance_ptr newStyle = style_instance_ptr(new style_instance(this, Name, DisplayName, Type, Content, IsAutomatic, IsDefault, + ParentStyleName, NextStyleName, DataStyleName, PercentageDataStyleName, StyleClass, ListStyleName, ListLevel, OutlineLevel)); + + instances_.push_back(newStyle); + int pos = static_cast(instances_.size() - 1); + + if (!Name.empty()) + { + std::wstring n = Name + L":" + boost::lexical_cast(style_family(Type)); + map_[n] = pos; + + // TODO: как правильно?? + std::wstring lName = XmlUtils::GetLower(Name); + //if ( boost::algorithm::contains(lName, L"internet_20_link") ) + if (lName == L"internet_20_link")///??????????????? + hyperlink_style_pos_ = pos; + } + + if (!DisplayName.empty()) + { + std::wstring n = DisplayName + L":" + boost::lexical_cast(style_family(Type)); + map2_[n] = pos; + } + + if (IsDefault) + default_map_[Type] = pos; + } - } - if (!find) - { - presentation_masters_instance::_master item; - item.master_name = master_name; - item.Id = content.size() +1; - item.rId = std::wstring(L"smId") + std::to_wstring(item.Id); - - content.push_back(item); - index = content.size()-1; - } - return std::pair(content[index].Id,content[index].rId); -} - -void presentation_masters_instance::add_layout_to(const std::wstring & master_name, presentation_layouts_instance::_layout & layout) -{ - bool find = false; - size_t index = 0; - for (index = 0; index < content.size(); index++) - { - if (content[index].master_name == master_name) + const std::wstring& style_instance::name() const { - find = true; - break; + return name_; } - } - if (find) - { - content[index].layouts.push_back(layout); + const std::wstring& style_instance::display_name() const + { + return display_name_; + } + style_family::type style_instance::type() const + { + return style_type_; + } + + style_content* style_instance::content() const + { + return content_; + } + + style_instance* style_instance::parent() const + { + if (parent_) + return parent_; + else if (container_) + parent_ = container_->style_by_name(parent_name_, type(), false); + + return parent_; + } + + const std::wstring& style_instance::parent_name() const + { + return parent_name_; + } + + style_instance* style_instance::next() const + { + if (next_) + return next_; + else if (container_ && next_name_.empty() == false) + next_ = container_->style_by_name(next_name_, type(), false); + + return next_; + } + + const std::wstring& style_instance::next_name() const + { + return next_name_; + } + + bool style_instance::is_automatic() const + { + return is_automatic_; + } + + bool style_instance::is_default() const + { + return is_default_; + } + const std::wstring& style_instance::percentage_data_style_name() const + { + return percentage_data_style_name_; + } + const std::wstring& style_instance::data_style_name() const + { + return data_style_name_; + } + _CP_OPT(std::wstring) style_instance::list_style_name() const + { + return list_style_name_; + } + const std::wstring& style_instance::style_class() const + { + return style_class_; + } + _CP_OPT(int) style_instance::list_level() const + { + return list_level_; + } + _CP_OPT(int) style_instance::outline_level() const + { + return outline_level_; + } + + style_instance* styles_container::style_by_name(const std::wstring& Name, style_family::type Type, bool object_in_styles) const + { + std::wstring n = L""; + if (object_in_styles) n = L"common:"; + n = n + Name + L":" + boost::lexical_cast(style_family(Type)); + + map_wstring_int_t::const_iterator res = map_.find(n); + + if (res != map_.end()) + { + int index = res->second; + return instances_[index].get(); + } + else if (object_in_styles) + { + //try automatic + n = Name + L":" + boost::lexical_cast(style_family(Type)); + + map_wstring_int_t::const_iterator res = map_.find(n); + + if (res != map_.end()) + { + int index = res->second; + return instances_[index].get(); + } + } + return NULL; + } + style_instance* styles_container::style_by_display_name(const std::wstring& Name, style_family::type Type, bool object_in_styles) const + { + std::wstring n = L""; + if (object_in_styles) n = L"common:"; + n = n + Name + L":" + boost::lexical_cast(style_family(Type)); + + map_wstring_int_t::const_iterator res = map2_.find(n); + + if (res != map2_.end()) + { + int index = res->second; + return instances_[index].get(); + } + else + return NULL; + } + void styles_container::add_master_page_name(const std::wstring& StyleName, const std::wstring& MasterPageName) + { + master_page_name_[StyleName] = MasterPageName; + } + + std::pair presentation_layouts_instance::add_or_find(const std::wstring& layout_name, const std::wstring& master_name) + { + std::map::iterator pFind = mapUsed.find(master_name + layout_name); + + if (pFind == mapUsed.end()) + { + presentation_layouts_instance::_layout item; + item.layout_name = layout_name; + item.master_name = master_name; + item.Id = content.size() + 1; + item.rId = std::wstring(L"lrId") + std::to_wstring(item.Id); + + content.push_back(item); + + mapUsed.insert(std::make_pair(master_name + layout_name, content.size() - 1)); + return std::pair(item.Id, item.rId); + } + else + { + return std::pair(content[pFind->second].Id, content[pFind->second].rId); + } + } + + std::pair presentation_masters_instance::add_or_find(const std::wstring& master_name) + { + std::map::iterator pFind = mapUsed.find(master_name); + + if (pFind == mapUsed.end()) + { + presentation_masters_instance::_master item; + item.master_name = master_name; + item.Id = content.size() + 1; + item.rId = std::wstring(L"smId") + std::to_wstring(item.Id); + + content.push_back(item); + + mapUsed.insert(std::make_pair(master_name, content.size() - 1)); + return std::pair(item.Id, item.rId); + } + else + { + return std::pair(content[pFind->second].Id, content[pFind->second].rId); + } + } + + void presentation_masters_instance::add_layout_to(const std::wstring& master_name, presentation_layouts_instance::_layout& layout) + { + std::map::iterator pFind = mapUsed.find(master_name); + + if (pFind != mapUsed.end()) + { + content[pFind->second].layouts.push_back(layout); + + } + } + + const _CP_OPT(std::wstring) styles_container::master_page_name_by_name(const std::wstring& StyleName) const + { + _CP_OPT(std::wstring) master_page; + + map_wstring_wstring::const_iterator res = master_page_name_.find(StyleName); + if (res != master_page_name_.end()) + master_page = res->second; + return master_page; + } + + style_instance* styles_container::style_default_by_type(style_family::type Type) const + { + map_style_family_int::const_iterator res = default_map_.find(Type); + if (res != default_map_.end()) + return instances_[res->second].get(); + else + return NULL; + } + + page_layout_instance::page_layout_instance(const style_page_layout* StylePageLayout) : style_page_layout_(StylePageLayout) + { + } + + const std::wstring& page_layout_instance::name() const + { + return style_page_layout_->style_name_; + } + + style_page_layout_properties* page_layout_instance::properties() const + { + return dynamic_cast(style_page_layout_->style_page_layout_properties_.get()); + } + + void page_layout_instance::xlsx_serialize(std::wostream& strm, oox::xlsx_conversion_context& Context) + { + const style_header_style* headerStyle = dynamic_cast(style_page_layout_->style_header_style_.get()); + const style_footer_style* footerStyle = dynamic_cast(style_page_layout_->style_footer_style_.get()); + + style_header_footer_properties* headerProp = headerStyle ? dynamic_cast(headerStyle->style_header_footer_properties_.get()) : NULL; + style_header_footer_properties* footerProp = footerStyle ? dynamic_cast(footerStyle->style_header_footer_properties_.get()) : NULL; + + if (headerProp) + { + const style_header_footer_properties_attlist& attr = headerProp->style_header_footer_properties_attlist_; + _CP_OPT(double) header; + + if (attr.fo_min_height_) header = attr.fo_min_height_->get_value_unit(length::pt); + else if (attr.svg_height_) header = attr.svg_height_->get_value_unit(length::pt); + + Context.get_table_context().set_header_page(header); + } + + if (footerProp) + { + const style_header_footer_properties_attlist& attr = footerProp->style_header_footer_properties_attlist_; + _CP_OPT(double) footer; + + if (attr.fo_min_height_) footer = attr.fo_min_height_->get_value_unit(length::pt); + else if (attr.svg_height_) footer = attr.svg_height_->get_value_unit(length::pt); + + Context.get_table_context().set_footer_page(footer); + } + + style_page_layout_properties* props = properties(); + if (props) + props->xlsx_serialize(strm, Context); + } + + void page_layout_instance::docx_serialize(std::wostream& strm, oox::docx_conversion_context& Context) + { + const style_header_style* headerStyle = dynamic_cast(style_page_layout_->style_header_style_.get()); + const style_footer_style* footerStyle = dynamic_cast(style_page_layout_->style_footer_style_.get()); + + style_header_footer_properties* headerProp = headerStyle ? dynamic_cast(headerStyle->style_header_footer_properties_.get()) : NULL; + style_header_footer_properties* footerProp = footerStyle ? dynamic_cast(footerStyle->style_header_footer_properties_.get()) : NULL; + + Context.get_header_footer_context().reset(); + + if (headerProp) + { + const style_header_footer_properties_attlist& attr = headerProp->style_header_footer_properties_attlist_; + _CP_OPT(length) top = attr.fo_min_height_ ? attr.fo_min_height_ : attr.svg_height_; + Context.get_header_footer_context().set_header(top); + } + + if (footerProp) + { + const style_header_footer_properties_attlist& attr = footerProp->style_header_footer_properties_attlist_; + _CP_OPT(length) bottom = attr.fo_min_height_ ? attr.fo_min_height_ : attr.svg_height_; + Context.get_header_footer_context().set_footer(bottom); + } + + if (style_page_layout_->style_page_usage_.get_type() == page_usage::Mirrored) + { + Context.set_settings_property(odf_reader::_property(L"mirrorMargins", true)); + } + + style_page_layout_properties* props = properties(); + if (props) + props->docx_serialize(strm, Context); + } + void page_layout_instance::pptx_serialize(std::wostream& strm, oox::pptx_conversion_context& Context) + { + style_page_layout_properties* props = properties(); + if (props) + props->pptx_serialize(strm, Context); + } + + void page_layout_container::add_page_layout(const style_page_layout* StylePageLayout) + { + page_layout_instance_ptr instance = page_layout_instance_ptr(new page_layout_instance(StylePageLayout)); + instances_.push_back(instance); + const int pos = static_cast(instances_.size() - 1); + + page_layout_names_[instance->name()] = pos; + + } + + void page_layout_container::add_master_page(const std::wstring& StyleName, const std::wstring& PageLayoutName, style_master_page* MasterPage) + { + master_page_names_array_.push_back(StyleName); + master_page_names_[StyleName] = PageLayoutName; + + master_pages_.push_back(MasterPage); + const int pos = static_cast(master_pages_.size() - 1); + master_page_names_2_[StyleName] = pos; + } + + void page_layout_container::add_presentation_page_layout(const std::wstring& StyleName, style_presentation_page_layout* StylePageLayout) + { + presentation_page_layouts_.push_back(StylePageLayout); + + const int pos = static_cast(presentation_page_layouts_.size() - 1); + presentation_page_layout_names_[StyleName] = pos; + } + + + const std::wstring page_layout_container::page_layout_name_by_style(const std::wstring& StyleName) const + { + if (master_page_names_.count(StyleName) > 0) + return master_page_names_.at(StyleName); + return L""; + } + + const page_layout_instance* page_layout_container::page_layout_by_style(const std::wstring& StyleName) const + { + if (master_page_names_.count(StyleName) > 0) + if (page_layout_names_.count(master_page_names_.at(StyleName))) + return instances_[page_layout_names_.at(master_page_names_.at(StyleName))].get(); + return NULL; + } + + page_layout_instance* page_layout_container::page_layout_by_name(const std::wstring& Name) const + { + if (page_layout_names_.count(Name)) + return instances_[page_layout_names_.at(Name)].get(); + return NULL; + } + + const page_layout_instance* page_layout_container::page_layout_first() const + { + if (master_page_names_array_.empty()) + return NULL; + + return page_layout_by_style(master_page_names_array_[0]); + } + bool page_layout_container::compare_page_properties(const std::wstring& master1, const std::wstring& master2) + { + const page_layout_instance* page_layout1 = page_layout_by_style(master1); + const page_layout_instance* page_layout2 = page_layout_by_style(master2); + + if (!page_layout1 || !page_layout2) return true; + if (!page_layout1->style_page_layout_ || !page_layout1->style_page_layout_) return true; + + style_page_layout_properties* props1 = dynamic_cast(page_layout1->style_page_layout_->style_page_layout_properties_.get()); + style_page_layout_properties* props2 = dynamic_cast(page_layout2->style_page_layout_->style_page_layout_properties_.get()); + + if (!props1 || !props2) return true; + + if (props1 == props2) return true; + + return props1->attlist_.compare(props2->attlist_); + } + + style_presentation_page_layout* page_layout_container::presentation_page_layout_by_name(const std::wstring& Name) + { + style_presentation_page_layout* res = NULL; + + if (presentation_page_layout_names_.count(Name)) + { + int ind = presentation_page_layout_names_.at(Name); + res = presentation_page_layouts_[ind]; + } + + return res; + } + style_master_page* page_layout_container::master_page_by_name(const std::wstring& Name) + { + style_master_page* res = NULL; + + if (master_page_names_2_.count(Name)) + res = master_pages_[master_page_names_2_.at(Name)]; + + return res; + } + + font_instance::font_instance(const std::wstring& StyleName, + const std::wstring& Name, + const std::wstring& Charset, + const std::wstring& Family, + const std::wstring& Pitch, + const std::wstring& AltName) : style_name_(StyleName), name_(Name), charset_(Charset), family_(Family), pitch_(Pitch), alt_name_(AltName) + {} + + const std::wstring& font_instance::style_name() const + { + return style_name_; + } + + const std::wstring& font_instance::name() const + { + return name_; + } + + const std::wstring& font_instance::charset() const + { + return charset_; + } + + const std::wstring& font_instance::family() const + { + return family_; + } + + const std::wstring& font_instance::pitch() const + { + return pitch_; + } + + const std::wstring& font_instance::alt_name() const + { + return alt_name_; + } + + font_instance* fonts_container::font_by_style_name(const std::wstring& StyleName) + { + if (font_style_names_.count(StyleName) > 0) + return instances_[font_style_names_.at(StyleName)].get(); + return NULL; + } + + font_instance* fonts_container::font_by_name(const std::wstring& Name) + { + if (font_names_.count(Name) > 0) + return instances_[font_names_.at(Name)].get(); + return NULL; + } + + void fonts_container::add_font(font_instance_ptr FontInstance) + { + instances_.push_back(FontInstance); + if (FontInstance) + { + font_style_names_[FontInstance->style_name()] = static_cast(instances_.size() - 1); + font_names_[FontInstance->name()] = static_cast(instances_.size() - 1); + } + } + + void list_style_container::add_list_style(text_list_style* textListStyle) + { + if (!textListStyle) return; + + instances_.push_back(list_style_instance_ptr(new list_style_instance(textListStyle))); + list_style_names_[textListStyle->attr_.style_name_] = static_cast(instances_.size() - 1); + } + + void list_style_container::add_list_style(text_list_style* textListStyle, const std::wstring& NewName) + { + if (!textListStyle) return; + + instances_.push_back(list_style_instance_ptr(new list_style_instance(textListStyle, NewName))); + list_style_names_[NewName] = static_cast(instances_.size() - 1); + } + void list_style_container::add_outline_style(text_outline_style* textOutlineStyle) + { + if (!textOutlineStyle) return; + + outline_ = textOutlineStyle; + outline_id_ = instances_.size(); + } + text_list_style* list_style_container::list_style_by_name(const std::wstring& Name) + { + if (list_style_names_.count(Name) > 0) + return instances_[list_style_names_.at(Name)]->get_text_list_style(); + return NULL; + } + + text_outline_style* list_style_container::outline_style() + { + return outline_; + } + int list_style_container::id_outline() + { + return outline_id_ + 1; + } + + int list_style_container::id_by_name(const std::wstring& Name) + { + if (list_style_names_.count(Name) > 0) + return list_style_names_.at(Name) + 1; + else + return 0; + } + const text_notes_configuration* notes_configuration::getConfiguration(odf_types::noteclass::type noteType) const + { + if (type_to_name_.count(noteType)) + return type_to_name_.at(noteType); + else + return NULL; + } + + void notes_configuration::add(odf_types::noteclass::type noteType, const text_notes_configuration* conf) + { + type_to_name_[noteType] = conf; + } + } } - -const _CP_OPT(std::wstring) styles_container::master_page_name_by_name(const std::wstring & StyleName) const -{ - _CP_OPT(std::wstring) master_page; - - map_wstring_wstring::const_iterator res = master_page_name_.find(StyleName); - if (res != master_page_name_.end()) - master_page = res->second; - return master_page; -} - -style_instance * styles_container::style_default_by_type(style_family::type Type) const -{ - map_style_family_int::const_iterator res = default_map_.find(Type); - if (res != default_map_.end()) - return instances_[res->second].get(); - else - return NULL; -} - -page_layout_instance::page_layout_instance(const style_page_layout * StylePageLayout) : style_page_layout_(StylePageLayout) -{ -} - -const std::wstring & page_layout_instance::name() const -{ - return style_page_layout_->style_name_; -} - -style_page_layout_properties * page_layout_instance::properties() const -{ - return dynamic_cast(style_page_layout_->style_page_layout_properties_.get()); -} - -void page_layout_instance::xlsx_serialize(std::wostream & strm, oox::xlsx_conversion_context & Context) -{ - const style_header_style * headerStyle = dynamic_cast(style_page_layout_->style_header_style_.get()); - const style_footer_style * footerStyle = dynamic_cast(style_page_layout_->style_footer_style_.get()); - - style_header_footer_properties * headerProp = headerStyle ? dynamic_cast(headerStyle->style_header_footer_properties_.get()) : NULL; - style_header_footer_properties * footerProp = footerStyle ? dynamic_cast(footerStyle->style_header_footer_properties_.get()) : NULL; - - if (headerProp) - { - const style_header_footer_properties_attlist & attr = headerProp->style_header_footer_properties_attlist_; - _CP_OPT(double) header; - - if (attr.fo_min_height_) header = attr.fo_min_height_->get_value_unit(length::pt); - else if (attr.svg_height_) header = attr.svg_height_->get_value_unit(length::pt); - - Context.get_table_context().set_header_page(header); - } - - if (footerProp) - { - const style_header_footer_properties_attlist & attr = footerProp->style_header_footer_properties_attlist_; - _CP_OPT(double) footer; - - if (attr.fo_min_height_) footer = attr.fo_min_height_->get_value_unit(length::pt); - else if (attr.svg_height_) footer = attr.svg_height_->get_value_unit(length::pt); - - Context.get_table_context().set_footer_page(footer); - } - - style_page_layout_properties * props = properties(); - if (props) - props->xlsx_serialize(strm, Context); -} - -void page_layout_instance::docx_serialize(std::wostream & strm, oox::docx_conversion_context & Context) -{ - const style_header_style * headerStyle = dynamic_cast(style_page_layout_->style_header_style_.get()); - const style_footer_style * footerStyle = dynamic_cast(style_page_layout_->style_footer_style_.get()); - - style_header_footer_properties * headerProp = headerStyle ? dynamic_cast(headerStyle->style_header_footer_properties_.get()) : NULL; - style_header_footer_properties * footerProp = footerStyle ? dynamic_cast(footerStyle->style_header_footer_properties_.get()) : NULL; - - Context.get_header_footer_context().reset(); - - if (headerProp) - { - const style_header_footer_properties_attlist & attr = headerProp->style_header_footer_properties_attlist_; - _CP_OPT(length) top = attr.fo_min_height_ ? attr.fo_min_height_ : attr.svg_height_; - Context.get_header_footer_context().set_header(top); - } - - if (footerProp) - { - const style_header_footer_properties_attlist & attr = footerProp->style_header_footer_properties_attlist_; - _CP_OPT(length) bottom = attr.fo_min_height_ ? attr.fo_min_height_ : attr.svg_height_; - Context.get_header_footer_context().set_footer(bottom); - } - - if ( style_page_layout_->style_page_usage_.get_type() == page_usage::Mirrored ) - { - Context.set_settings_property(odf_reader::_property(L"mirrorMargins",true)); - } - - style_page_layout_properties * props = properties(); - if (props) - props->docx_serialize(strm, Context); -} -void page_layout_instance::pptx_serialize(std::wostream & strm, oox::pptx_conversion_context & Context) -{ - style_page_layout_properties * props = properties(); - if (props) - props->pptx_serialize(strm, Context); -} - -void page_layout_container::add_page_layout(const style_page_layout * StylePageLayout) -{ - page_layout_instance_ptr instance = page_layout_instance_ptr( new page_layout_instance(StylePageLayout) ); - instances_.push_back(instance); - const int pos = static_cast(instances_.size() - 1); - - page_layout_names_[ instance->name() ] = pos; - -} - -void page_layout_container::add_master_page(const std::wstring & StyleName, const std::wstring & PageLayoutName, style_master_page* MasterPage) -{ - master_page_names_array_.push_back(StyleName); - master_page_names_[StyleName] = PageLayoutName; - - master_pages_.push_back(MasterPage); - const int pos = static_cast(master_pages_.size() - 1); - master_page_names_2_[StyleName] = pos; -} - -void page_layout_container::add_presentation_page_layout(const std::wstring & StyleName, style_presentation_page_layout* StylePageLayout) -{ - presentation_page_layouts_.push_back(StylePageLayout); - - const int pos = static_cast(presentation_page_layouts_.size() - 1); - presentation_page_layout_names_[ StyleName ] = pos; - -} - - -const std::wstring page_layout_container::page_layout_name_by_style(const std::wstring & StyleName) const -{ - if (master_page_names_.count(StyleName) > 0) - return master_page_names_.at(StyleName); - return L""; -} - -const page_layout_instance * page_layout_container::page_layout_by_style(const std::wstring & StyleName) const -{ - if (master_page_names_.count(StyleName) > 0) - if (page_layout_names_.count(master_page_names_.at(StyleName)) ) - return instances_[ page_layout_names_.at( master_page_names_.at(StyleName) ) ].get(); - return NULL; -} - -page_layout_instance * page_layout_container::page_layout_by_name(const std::wstring & Name) const -{ - if (page_layout_names_.count(Name)) - return instances_[ page_layout_names_.at( Name ) ].get(); - return NULL; -} - -const page_layout_instance * page_layout_container::page_layout_first() const -{ - if (master_page_names_array_.empty()) - return NULL; - - return page_layout_by_style(master_page_names_array_[0]); -} -bool page_layout_container::compare_page_properties(const std::wstring & master1, const std::wstring & master2) -{ - const page_layout_instance *page_layout1 = page_layout_by_style(master1); - const page_layout_instance *page_layout2 = page_layout_by_style(master2); - - if (!page_layout1 || !page_layout2) return true; - if (!page_layout1->style_page_layout_ || !page_layout1->style_page_layout_) return true; - - style_page_layout_properties *props1 = dynamic_cast(page_layout1->style_page_layout_->style_page_layout_properties_.get()); - style_page_layout_properties *props2 = dynamic_cast(page_layout2->style_page_layout_->style_page_layout_properties_.get()); - - if (!props1 || !props2) return true; - - if (props1 == props2) return true; - - return props1->attlist_.compare(props2->attlist_); -} - -style_presentation_page_layout * page_layout_container::presentation_page_layout_by_name(const std::wstring & Name) -{ - style_presentation_page_layout * res = NULL; - - if (presentation_page_layout_names_.count(Name)) - { - int ind = presentation_page_layout_names_.at( Name ) ; - res = presentation_page_layouts_[ind]; - } - - return res; -} -style_master_page * page_layout_container::master_page_by_name(const std::wstring & Name) -{ - style_master_page * res = NULL; - - if (master_page_names_2_.count(Name)) - res = master_pages_[ master_page_names_2_.at( Name ) ]; - - return res; -} - -font_instance::font_instance( const std::wstring & StyleName, - const std::wstring & Name, - const std::wstring & Charset, - const std::wstring & Family, - const std::wstring & Pitch, - const std::wstring & AltName) : style_name_(StyleName), name_(Name), charset_(Charset), family_(Family), pitch_(Pitch), alt_name_(AltName) -{} - -const std::wstring & font_instance::style_name() const -{ - return style_name_; -} - -const std::wstring & font_instance::name() const -{ - return name_; -} - -const std::wstring & font_instance::charset() const -{ - return charset_; -} - -const std::wstring & font_instance::family() const -{ - return family_; -} - -const std::wstring & font_instance::pitch() const -{ - return pitch_; -} - -const std::wstring & font_instance::alt_name() const -{ - return alt_name_; -} - -font_instance * fonts_container::font_by_style_name(const std::wstring & StyleName) -{ - if (font_style_names_.count(StyleName) > 0) - return instances_[font_style_names_.at(StyleName)].get(); - return NULL; -} - -font_instance * fonts_container::font_by_name(const std::wstring & Name) -{ - if (font_names_.count(Name) > 0) - return instances_[font_names_.at(Name)].get(); - return NULL; -} - -void fonts_container::add_font( font_instance_ptr FontInstance ) -{ - instances_.push_back(FontInstance); - if (FontInstance) - { - font_style_names_[FontInstance->style_name()] = static_cast(instances_.size() - 1); - font_names_[FontInstance->name()] = static_cast(instances_.size() - 1); - } -} - -void list_style_container::add_list_style(text_list_style * textListStyle) -{ - if (!textListStyle) return; - - instances_.push_back( list_style_instance_ptr(new list_style_instance(textListStyle)) ); - list_style_names_[ textListStyle->attr_.style_name_ ] = static_cast(instances_.size() - 1); -} - -void list_style_container::add_list_style(text_list_style * textListStyle, const std::wstring & NewName) -{ - if (!textListStyle) return; - - instances_.push_back( list_style_instance_ptr(new list_style_instance(textListStyle, NewName)) ); - list_style_names_[NewName] = static_cast(instances_.size() - 1); -} -void list_style_container::add_outline_style(text_outline_style *textOutlineStyle) -{ - if (!textOutlineStyle) return; - - outline_ = textOutlineStyle; - outline_id_ = instances_.size(); -} -text_list_style * list_style_container::list_style_by_name(const std::wstring & Name) -{ - if (list_style_names_.count(Name) > 0) - return instances_[list_style_names_.at(Name)]->get_text_list_style(); - return NULL; -} - -text_outline_style * list_style_container::outline_style() -{ - return outline_; -} -int list_style_container::id_outline() -{ - return outline_id_ + 1; -} - -int list_style_container::id_by_name(const std::wstring & Name) -{ - if (list_style_names_.count(Name) > 0) - return list_style_names_.at(Name) + 1; - else - return 0; -} -const text_notes_configuration * notes_configuration::getConfiguration(odf_types::noteclass::type noteType) const -{ - if (type_to_name_.count(noteType)) - return type_to_name_.at(noteType); - else - return NULL; -} - -void notes_configuration::add(odf_types::noteclass::type noteType, const text_notes_configuration * conf) -{ - type_to_name_[noteType] = conf; -} - -} -} diff --git a/OdfFile/Reader/Format/odfcontext.h b/OdfFile/Reader/Format/odfcontext.h index 82e6a55c65..751cdba747 100644 --- a/OdfFile/Reader/Format/odfcontext.h +++ b/OdfFile/Reader/Format/odfcontext.h @@ -131,6 +131,8 @@ public: }; std::vector<_layout> content; + std::map mapUsed; + std::pair add_or_find(const std::wstring & layout_name,const std::wstring & master_name); }; class presentation_masters_instance @@ -145,6 +147,7 @@ public: std::vector layouts; }; std::vector<_master> content; + std::map mapUsed; void add_layout_to(const std::wstring & master_name,presentation_layouts_instance::_layout & layout); @@ -238,9 +241,9 @@ class page_layout_container public: typedef std::vector instances_array; - void add_page_layout(const style_page_layout * StylePageLayout); - void add_master_page(const std::wstring & StyleName, const std::wstring & PageLayoutName,style_master_page* MasterPage); - void add_presentation_page_layout(const std::wstring & StyleName, style_presentation_page_layout* StylePageLayout); + void add_page_layout(const style_page_layout *stylePageLayout); + void add_master_page(const std::wstring & StyleName, const std::wstring & PageLayoutName, style_master_page* MasterPage); + void add_presentation_page_layout(const std::wstring & styleName, style_presentation_page_layout *stylePageLayout); const std::wstring page_layout_name_by_style(const std::wstring & StyleName) const; @@ -265,13 +268,13 @@ private: instances_array instances_; std::vector master_pages_; - boost::unordered_map page_layout_names_; + std::map page_layout_names_; std::vector master_page_names_array_; - boost::unordered_map master_page_names_; + std::map master_page_names_; - boost::unordered_map master_page_names_2_; + std::map master_page_names_2_; - boost::unordered_map presentation_page_layout_names_; + std::map presentation_page_layout_names_; odf_reader::text_linenumbering_configuration *linenumberingcConfiguration = NULL; }; diff --git a/OdfFile/Reader/Format/style_presentation.cpp b/OdfFile/Reader/Format/style_presentation.cpp index af38c24d12..805c6f1453 100644 --- a/OdfFile/Reader/Format/style_presentation.cpp +++ b/OdfFile/Reader/Format/style_presentation.cpp @@ -31,58 +31,74 @@ */ #include "style_presentation.h" +#include "odfcontext.h" +#include "odf_document.h" #include #include -namespace cpdoccore { +#include "calcs_styles.h" + +namespace cpdoccore { using namespace odf_types; -namespace odf_reader { + namespace odf_reader { -const wchar_t * presentation_placeholder::ns = L"presentation"; -const wchar_t * presentation_placeholder::name = L"placeholder"; + const wchar_t* presentation_placeholder::ns = L"presentation"; + const wchar_t* presentation_placeholder::name = L"placeholder"; -void presentation_placeholder::add_attributes( const xml::attributes_wc_ptr & Attributes ) -{ - CP_APPLY_ATTR(L"presentation:object", presentation_object_); - - CP_APPLY_ATTR(L"svg:height", svg_height_); - CP_APPLY_ATTR(L"svg:width", svg_width_); - CP_APPLY_ATTR(L"svg:x", svg_x_); - CP_APPLY_ATTR(L"svg:y", svg_y_); + void presentation_placeholder::add_attributes(const xml::attributes_wc_ptr& Attributes) + { + CP_APPLY_ATTR(L"presentation:object", presentation_object_); -} + CP_APPLY_ATTR(L"svg:height", svg_height_); + CP_APPLY_ATTR(L"svg:width", svg_width_); + CP_APPLY_ATTR(L"svg:x", svg_x_); + CP_APPLY_ATTR(L"svg:y", svg_y_); -void presentation_placeholder::add_child_element( xml::sax * Reader, const std::wstring & Ns, const std::wstring & Name) -{ - CP_NOT_APPLICABLE_ELM(); -} + CP_APPLY_ATTR(L"draw:text-style-name", text_style_name_); + } -void presentation_placeholder::pptx_convert(oox::pptx_conversion_context & Context) -{ - double cx = svg_width_.get_value_or(length(0)).get_value_unit(length::pt); - double cy = svg_height_.get_value_or(length(0)).get_value_unit(length::pt); + void presentation_placeholder::add_child_element(xml::sax* Reader, const std::wstring& Ns, const std::wstring& Name) + { + CP_NOT_APPLICABLE_ELM(); + } - //пока не понятно что значит отрицательная ширина ... - cx = fabs(cx); - cy = fabs(cy); - - double x = svg_x_.get_value_or(length(0)).get_value_unit(length::pt); - double y = svg_y_.get_value_or(length(0)).get_value_unit(length::pt); + void presentation_placeholder::pptx_convert(oox::pptx_conversion_context& Context) + { + double cx = svg_width_.get_value_or(length(0)).get_value_unit(length::pt); + double cy = svg_height_.get_value_or(length(0)).get_value_unit(length::pt); - Context.get_slide_context().start_shape(2);//rect - Context.get_slide_context().set_name(L"place_holder"); + //пока не понятно что значит отрицательная ширина ... + cx = fabs(cx); + cy = fabs(cy); - Context.get_slide_context().set_rect(cx,cy,x,y); - if (presentation_object_) - { - Context.get_slide_context().set_placeHolder_type(presentation_object_->get_type_ms()); - } + double x = svg_x_.get_value_or(length(0)).get_value_unit(length::pt); + double y = svg_y_.get_value_or(length(0)).get_value_unit(length::pt); - Context.get_slide_context().end_shape(); -} + Context.get_slide_context().start_shape(2);//rect + Context.get_slide_context().set_name(L"place_holder"); + + if (text_style_name_ && !text_style_name_->empty()) + { + Context.get_text_context().start_base_style(*text_style_name_, odf_types::style_family::Paragraph); + } + Context.get_slide_context().set_rect(cx, cy, x, y); + if (presentation_object_) + { + Context.get_slide_context().set_placeHolder_type(presentation_object_->get_type_ms()); + Context.get_slide_context().set_property(_property(L"no_rect", true)); + } + std::wstring text_content_ = Context.get_text_context().end_object(); + + if (!text_content_.empty()) + { + Context.get_slide_context().set_property(_property(L"text-content", text_content_)); + } + Context.get_text_context().end_base_style(); + Context.get_slide_context().end_shape(); + } //------------------------------------------------------------------------------------------------- const wchar_t * presentation_sound::ns = L"presentation"; const wchar_t * presentation_sound::name = L"sound"; diff --git a/OdfFile/Reader/Format/style_presentation.h b/OdfFile/Reader/Format/style_presentation.h index 302ce4271a..c603cbde6f 100644 --- a/OdfFile/Reader/Format/style_presentation.h +++ b/OdfFile/Reader/Format/style_presentation.h @@ -68,6 +68,7 @@ public: _CP_OPT(odf_types::presentation_class) presentation_object_; + _CP_OPT(std::wstring) text_style_name_; }; CP_REGISTER_OFFICE_ELEMENT2(presentation_placeholder); diff --git a/OdfFile/Writer/Converter/ConvertDrawing.cpp b/OdfFile/Writer/Converter/ConvertDrawing.cpp index 361d01dd8b..4e78643d96 100644 --- a/OdfFile/Writer/Converter/ConvertDrawing.cpp +++ b/OdfFile/Writer/Converter/ConvertDrawing.cpp @@ -1049,6 +1049,7 @@ void OoxConverter::convert(PPTX::Logic::PrstGeom *oox_geom) { odf_context()->drawing_context()->set_viewBox(21600, 21600); odf_context()->drawing_context()->set_path(L"U 10800 10800 10800 10800 0 360 Z N"); + odf_context()->drawing_context()->set_draw_type(L"circle"); return; } @@ -2103,6 +2104,12 @@ void OoxConverter::convert(PPTX::Logic::Paragraph *oox_paragraph, PPTX::Logic::T if (odf_context()->drawing_context()->is_wordart()) odf_context()->drawing_context()->set_paragraph_properties(paragraph_properties); + + if (styled && odf_context()->drawing_context()->is_placeholder()) + { + odf_writer::odf_style_state_ptr state = odf_context()->text_context()->get_styles_context()->last_state(odf_types::style_family::Paragraph); + odf_context()->drawing_context()->set_placeholder_style(state->get_name()); + } } std::vector::iterator runIt = std::find_if_not(oox_paragraph->RunElems.begin(), oox_paragraph->RunElems.end(), diff --git a/OdfFile/Writer/Converter/PptxConverter.cpp b/OdfFile/Writer/Converter/PptxConverter.cpp index 41a1fdaedc..f600b8b7b3 100644 --- a/OdfFile/Writer/Converter/PptxConverter.cpp +++ b/OdfFile/Writer/Converter/PptxConverter.cpp @@ -216,6 +216,7 @@ bool PptxConverter::convertDocument() //convert_meta(app_ptr.GetPointer(), core_ptr.GetPointer()); -> привести к OOX::... + convert_masters_and_layouts(); convert_slides(); //удалим уже ненужный документ pptx @@ -1211,7 +1212,6 @@ std::wstring PptxConverter::convert_animation_scale_values(int x, int y) return ss.str(); } - std::wstring PptxConverter::get_page_name(PPTX::Logic::CSld* oox_slide, _typePages type) { if (!oox_slide) @@ -1251,6 +1251,38 @@ void PptxConverter::fill_in_deferred_hyperlinks() } } + +void PptxConverter::convert_masters_and_layouts() +{ + for (size_t iMaster = 0; iMaster < presentation->sldMasterIdLst.size(); ++iMaster) + { + smart_ptr slideMaster = ((*presentation)[presentation->sldMasterIdLst[iMaster].rid.get()]).smart_dynamic_cast(); + + if (slideMaster.IsInit() == false) + continue; + + for (size_t iLayout = 0; iLayout < slideMaster->sldLayoutIdLst.size(); ++iLayout) + { + std::wstring rId = slideMaster->sldLayoutIdLst[iLayout].rid.get(); + smart_ptr slideLayout = ((*slideMaster)[rId]).smart_dynamic_cast(); + + if (false == slideLayout.IsInit()) continue; + + std::map::iterator pFind = m_mapLayouts.find(slideLayout->m_sOutputFilename); + if (pFind == m_mapLayouts.end()) + { + odp_context->start_layout_slide(); + convert_layout(&slideLayout->cSld); + odp_context->end_layout_slide(); + + std::wstring layout_style_name = odp_context->page_layout_context()->get_local_styles_context()->last_state(odf_types::style_family::PresentationPageLayout)->get_name(); + + m_mapLayouts.insert(std::make_pair(slideLayout->m_sOutputFilename, layout_style_name)); + } + } + } +} + void PptxConverter::convert_slides() { for (size_t i = 0; i < presentation->sldIdLst.size(); ++i) @@ -1339,7 +1371,7 @@ void PptxConverter::convert_slides() } pFind = m_mapLayouts.find(slide->Layout->m_sOutputFilename); if (pFind == m_mapLayouts.end()) - { + {//сюда уже не попадет - выше odp_context->start_layout_slide(); convert_layout(&slide->Layout->cSld); odp_context->end_layout_slide(); @@ -2666,7 +2698,7 @@ void PptxConverter::convert_layout(PPTX::Logic::CSld *oox_slide) odf_writer::office_element_ptr elm; create_element(L"presentation", L"placeholder", elm, odp_context); - odf_context()->drawing_context()->start_drawing(); + odf_context()->drawing_context()->start_drawing(); odf_context()->drawing_context()->start_element(elm); odf_context()->drawing_context()->set_placeholder_type(type); @@ -2675,6 +2707,7 @@ void PptxConverter::convert_layout(PPTX::Logic::CSld *oox_slide) odf_context()->drawing_context()->set_placeholder_id(*pShape->nvSpPr.nvPr.ph->idx); OoxConverter::convert(pShape->spPr.xfrm.GetPointer()); + OoxConverter::convert(pShape->txBody.GetPointer()); odf_context()->drawing_context()->end_element(); odf_context()->drawing_context()->end_drawing(); diff --git a/OdfFile/Writer/Converter/PptxConverter.h b/OdfFile/Writer/Converter/PptxConverter.h index adac57d9a0..0a2ee9c93a 100644 --- a/OdfFile/Writer/Converter/PptxConverter.h +++ b/OdfFile/Writer/Converter/PptxConverter.h @@ -228,11 +228,12 @@ private: std::wstring interactive_animation_element_id; - void convert_slides (); - void convert_styles (); - void convert_settings (); - void convert_layouts (); - void convert_common (); + void convert_slides (); + void convert_styles (); + void convert_settings (); + void convert_layouts (); + void convert_common (); + void convert_masters_and_layouts(); std::wstring convert_animation_formula(std::wstring formula); std::wstring convert_animation_scale_values(int x, int y); diff --git a/OdfFile/Writer/Format/draw_frame.h b/OdfFile/Writer/Format/draw_frame.h index 7d1df17a11..b80e7ff524 100644 --- a/OdfFile/Writer/Format/draw_frame.h +++ b/OdfFile/Writer/Format/draw_frame.h @@ -155,7 +155,7 @@ public: virtual void serialize(std::wostream & _Wostream); - odf_types::union_common_draw_attlists common_draw_attlists_; + odf_types::union_common_draw_attlists common_draw_attlists_; _CP_OPT(std::wstring) xml_id_; office_element_ptr_array content_; diff --git a/OdfFile/Writer/Format/draw_shapes.h b/OdfFile/Writer/Format/draw_shapes.h index e1e0199d35..4e0bc5bc36 100644 --- a/OdfFile/Writer/Format/draw_shapes.h +++ b/OdfFile/Writer/Format/draw_shapes.h @@ -47,19 +47,14 @@ public: static const ElementType type = typeDrawShape; - virtual void serialize(std::wostream & _Wostream); virtual void serialize_attlist(CP_ATTR_NODE); odf_types::common_xlink_attlist common_xlink_attlist_; _CP_OPT(std::wstring) draw_id_;//используется для анимашек - - - int sub_type_; - }; //---------------------------------------------------------------------------------------------- class draw_rect_attlist diff --git a/OdfFile/Writer/Format/odf_drawing_context.cpp b/OdfFile/Writer/Format/odf_drawing_context.cpp index 625e3c85a7..90a96d24c6 100644 --- a/OdfFile/Writer/Format/odf_drawing_context.cpp +++ b/OdfFile/Writer/Format/odf_drawing_context.cpp @@ -199,8 +199,8 @@ struct odf_drawing_state hidden_ = false; z_order_ = -1; - presentation_class_ = boost::none; - presentation_placeholder_ = boost::none; + presentation_class_ = boost::none; + presentation_placeholder_id_ = boost::none; rotateAngle_ = boost::none; text_rotateAngle_ = boost::none; @@ -219,6 +219,8 @@ struct odf_drawing_state flipH_ = flipV_ = false; + draw_type_ = boost::none; + } std::vector elements_; @@ -230,6 +232,8 @@ struct odf_drawing_state _CP_OPT(double) cx_; _CP_OPT(double) cy_; + _CP_OPT(std::wstring) draw_type_; + bool flipH_; bool flipV_; @@ -244,7 +248,7 @@ struct odf_drawing_state _CP_OPT(int) text_rotateAngle_; _CP_OPT(presentation_class) presentation_class_; - _CP_OPT(std::wstring) presentation_placeholder_; + _CP_OPT(std::wstring) presentation_placeholder_id_; std::wstring program_; std::wstring replacement_; @@ -417,7 +421,7 @@ void odf_drawing_context::start_group() if (false == impl_->current_level_.empty()) impl_->current_level_.back().elm->add_child_element(group_elm); - if (group == NULL)return; + if (group == NULL) return; //если группа топовая - то данные если не записать - сотрутся if (!impl_->current_drawing_state_.name_.empty()) @@ -595,7 +599,7 @@ void odf_drawing_context::end_drawing() draw_base* draw = impl_->current_drawing_state_.elements_.empty() ? NULL : dynamic_cast(impl_->current_drawing_state_.elements_[index].elm.get()); if (draw) { - if (impl_->current_drawing_state_.presentation_class_ || impl_->current_drawing_state_.presentation_placeholder_) + if (impl_->current_drawing_state_.presentation_class_ || impl_->current_drawing_state_.presentation_placeholder_id_) { _CP_OPT(std::wstring) draw_layer; if (impl_->is_presentation_.get() > 0) @@ -695,7 +699,7 @@ void odf_drawing_context::end_drawing() draw->common_draw_attlists_.rel_size_.common_draw_size_attlist_.svg_width_ = impl_->current_drawing_state_.svg_width_; } /////////////////////////////////////////////////////// - presentation_placeholder * placeholder = impl_->current_drawing_state_.elements_.empty() ? NULL : dynamic_cast(impl_->current_drawing_state_.elements_[index].elm.get()); + presentation_placeholder *placeholder = impl_->current_drawing_state_.elements_.empty() ? NULL : dynamic_cast(impl_->current_drawing_state_.elements_[index].elm.get()); if (placeholder) { placeholder->presentation_object_ = impl_->current_drawing_state_.presentation_class_; @@ -890,6 +894,14 @@ bool odf_drawing_context::is_wordart() return false; } +bool odf_drawing_context::is_placeholder() +{ + if (!impl_->current_level_.empty() && typeStylePresentationPlaceholder == impl_->current_level_[0].elm->get_type()) + return true; + + return false; +} + bool odf_drawing_context::change_text_box_2_wordart() { if (impl_->current_drawing_state_.oox_shape_preset_ > 2000 && impl_->current_drawing_state_.oox_shape_preset_ < 3000) @@ -1107,6 +1119,10 @@ void odf_drawing_context::end_shape() { text_shape = true; } + else if (impl_->current_drawing_state_.draw_type_) + { + sub_type = *impl_->current_drawing_state_.draw_type_; + } //else //{ // sub_type = L"polyline"; @@ -1310,7 +1326,7 @@ void odf_drawing_context::end_frame() end_element(); } ///////////////////// -void odf_drawing_context::start_element(office_element_ptr elm, office_element_ptr style_elm) +void odf_drawing_context::start_element(office_element_ptr elm, office_element_ptr style_elm) { size_t level = impl_->current_level_.size(); @@ -1368,8 +1384,10 @@ void odf_drawing_context::end_area_properties() } void odf_drawing_context::start_line_properties(bool reset) { + if (!impl_->current_graphic_properties) return; + impl_->current_drawing_part_ = Line; - if (reset) + if (reset ) impl_->current_graphic_properties->draw_stroke_ = boost::none; } void odf_drawing_context::end_line_properties() @@ -1403,7 +1421,7 @@ void odf_drawing_context::set_hidden (bool bVal) } void odf_drawing_context::set_opacity(double percent_) { - if (!impl_->current_graphic_properties)return; + if (!impl_->current_graphic_properties) return; switch(impl_->current_drawing_part_) { @@ -1460,7 +1478,7 @@ void odf_drawing_context::set_placeholder_id (std::wstring val) { if (!impl_->is_presentation_) return; - impl_->current_drawing_state_.presentation_placeholder_ = val; + impl_->current_drawing_state_.presentation_placeholder_id_ = val; } void odf_drawing_context::set_placeholder_type (int val) { @@ -1704,6 +1722,11 @@ void odf_drawing_context::add_handle (std::wstring x, std::wstring y, std::wstri impl_->current_drawing_state_.oox_shape_->handles.push_back(h); } +void odf_drawing_context::set_draw_type(const std::wstring& draw_type) +{ + impl_->current_drawing_state_.draw_type_ = draw_type; +} + void odf_drawing_context::add_formula (std::wstring name, std::wstring fmla) { if (!impl_->current_drawing_state_.oox_shape_) return; @@ -2506,6 +2529,16 @@ void odf_drawing_context::set_text_properties(style_text_properties *text_proper set_text_properties(&text_properties->content_); } +void odf_drawing_context::set_placeholder_style(const std::wstring& style_name) +{ + if (impl_->current_drawing_state_.elements_.empty()) return; + + presentation_placeholder* placeholder = dynamic_cast(impl_->current_drawing_state_.elements_[0].elm.get()); + if (placeholder) + { + placeholder->text_style_name_ = style_name; + } +} void odf_drawing_context::set_paragraph_properties(paragraph_format_properties *paragraph_properties) { if (impl_->current_drawing_state_.elements_.empty()) return; @@ -2515,7 +2548,7 @@ void odf_drawing_context::set_paragraph_properties(paragraph_format_properties * draw_base* draw = dynamic_cast(impl_->current_drawing_state_.elements_[0].elm.get()); if (draw) { - if(!draw->common_draw_attlists_.shape_with_text_and_styles_.common_shape_draw_attlist_.draw_text_style_name_) + if (!draw->common_draw_attlists_.shape_with_text_and_styles_.common_shape_draw_attlist_.draw_text_style_name_) { impl_->styles_context_->create_style(L"", style_family::Paragraph, true, false, -1); @@ -2680,7 +2713,7 @@ void odf_drawing_context::set_textarea_writing_mode(int mode) if (draw) { style* style_ = NULL; - if(!draw->common_draw_attlists_.shape_with_text_and_styles_.common_shape_draw_attlist_.draw_text_style_name_) + if (!draw->common_draw_attlists_.shape_with_text_and_styles_.common_shape_draw_attlist_.draw_text_style_name_) { impl_->styles_context_->create_style(L"", style_family::Paragraph, true, false, -1); diff --git a/OdfFile/Writer/Format/odf_drawing_context.h b/OdfFile/Writer/Format/odf_drawing_context.h index 0582aa5067..c38725eb43 100644 --- a/OdfFile/Writer/Format/odf_drawing_context.h +++ b/OdfFile/Writer/Format/odf_drawing_context.h @@ -151,6 +151,7 @@ public: bool change_text_box_2_wordart(); bool is_wordart(); bool is_text_box(); + bool is_placeholder(); graphic_format_properties* get_graphic_properties(); @@ -158,6 +159,8 @@ public: void set_paragraph_properties (paragraph_format_properties *paragraph_properties); void set_text_properties (style_text_properties *text_properties); void set_text_properties (text_format_properties* text_properties); + + void set_placeholder_style(const std::wstring& style_name); void start_text_box (); void set_text_box_min_size (bool val); @@ -205,6 +208,7 @@ public: void set_textarea (std::wstring l, std::wstring t, std::wstring r, std::wstring b); void add_handle (std::wstring x, std::wstring y, std::wstring refX, std::wstring refY, std::wstring minX, std::wstring maxX, std::wstring minY, std::wstring maxY); + void set_draw_type (const std::wstring& draw_type); void set_viewBox (double W, double H); diff --git a/OdfFile/Writer/Format/odp_slide_context.cpp b/OdfFile/Writer/Format/odp_slide_context.cpp index 1210212f01..091945ee7b 100644 --- a/OdfFile/Writer/Format/odp_slide_context.cpp +++ b/OdfFile/Writer/Format/odp_slide_context.cpp @@ -191,7 +191,7 @@ void odp_slide_context::start_table_row (bool styled) if (styled) { - styles_context_->create_style(L"",odf_types::style_family::TableRow, true, false, -1); + styles_context_->create_style(L"", odf_types::style_family::TableRow, true, false, -1); odf_style_state_ptr style_state = styles_context_->last_state(style_family::TableRow); if (style_state) diff --git a/OdfFile/Writer/Format/style_presentation.cpp b/OdfFile/Writer/Format/style_presentation.cpp index 64fb1b722a..ae1311b095 100644 --- a/OdfFile/Writer/Format/style_presentation.cpp +++ b/OdfFile/Writer/Format/style_presentation.cpp @@ -58,7 +58,7 @@ void presentation_placeholder::serialize(std::wostream & strm) CP_XML_ATTR_OPT(L"svg:width", svg_width_); CP_XML_ATTR_OPT(L"svg:x", svg_x_); CP_XML_ATTR_OPT(L"svg:y", svg_y_); - + CP_XML_ATTR_OPT(L"draw:text-style-name", text_style_name_); } } } diff --git a/OdfFile/Writer/Format/style_presentation.h b/OdfFile/Writer/Format/style_presentation.h index 30225dad3e..eccda39622 100644 --- a/OdfFile/Writer/Format/style_presentation.h +++ b/OdfFile/Writer/Format/style_presentation.h @@ -47,7 +47,7 @@ namespace cpdoccore { namespace odf_writer { -class presentation_placeholder : public office_element_impl +class presentation_placeholder : public office_element_impl //draw_base ?? { public: static const wchar_t * ns; @@ -55,22 +55,20 @@ public: static const ElementType type = typeStylePresentationPlaceholder; - - virtual void create_child_element(const std::wstring & Ns, const std::wstring & Name){} virtual void add_child_element( const office_element_ptr & child){} virtual void serialize(std::wostream & strm); - + _CP_OPT(odf_types::length) svg_x_; _CP_OPT(odf_types::length) svg_y_; _CP_OPT(odf_types::length) svg_width_; _CP_OPT(odf_types::length) svg_height_; _CP_OPT(odf_types::presentation_class) presentation_object_; - +//additional + _CP_OPT(std::wstring) text_style_name_; }; - CP_REGISTER_OFFICE_ELEMENT2(presentation_placeholder); //---------------------------------------------------------------------------------- diff --git a/PdfFile/PdfFile.cpp b/PdfFile/PdfFile.cpp index 11a1570230..5d84fe953d 100644 --- a/PdfFile/PdfFile.cpp +++ b/PdfFile/PdfFile.cpp @@ -1292,6 +1292,12 @@ BYTE* CPdfFile::GetWidgets() return NULL; return m_pInternal->pReader->GetWidgets(); } +BYTE* CPdfFile::GetWidgetFonts() +{ + if (!m_pInternal->pReader) + return NULL; + return m_pInternal->pReader->GetWidgetFonts(); +} BYTE* CPdfFile::GetAnnots(int nPageIndex) { if (!m_pInternal->pReader) diff --git a/PdfFile/PdfFile.h b/PdfFile/PdfFile.h index 86fc7c791d..1611a92a2a 100644 --- a/PdfFile/PdfFile.h +++ b/PdfFile/PdfFile.h @@ -129,6 +129,7 @@ public: int GetRotate(int nPageIndex); int GetMaxRefID(); BYTE* GetWidgets(); + BYTE* GetWidgetFonts(); BYTE* GetAnnots (int nPageIndex = -1); BYTE* VerifySign (const std::wstring& sFile, ICertificate* pCertificate, int nWidget = -1); BYTE* GetAPWidget (int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nWidget = -1, const char* sView = NULL, const char* sBView = NULL); diff --git a/PdfFile/PdfReader.cpp b/PdfFile/PdfReader.cpp index a7171d0cff..80e215df0e 100644 --- a/PdfFile/PdfReader.cpp +++ b/PdfFile/PdfReader.cpp @@ -883,6 +883,126 @@ BYTE* CPdfReader::GetWidgets() oRes.ClearWithoutAttack(); return bRes; } +BYTE* CPdfReader::GetWidgetFonts() +{ + if (!m_pPDFDocument || !m_pPDFDocument->getCatalog()) + return NULL; + + AcroForm* pAcroForms = m_pPDFDocument->getCatalog()->getForm(); + XRef* xref = m_pPDFDocument->getXRef(); + if (!pAcroForms || !xref) + return NULL; + + NSWasm::CData oRes; + oRes.SkipLen(); + + int nFontsID = 0; + int nFontsPos = oRes.GetSize(); + oRes.AddInt(nFontsID); + + std::vector arrFontsRef; + for (int i = 0, nNum = pAcroForms->getNumFields(); i < nNum; ++i) + { + AcroFormField* pField = pAcroForms->getField(i); + if (!pField) + continue; + + // Шрифт и размер шрифта - из DA + Ref fontID; + double dFontSize = 0; + pField->getFont(&fontID, &dFontSize); + if (fontID.num < 0 || std::find(arrFontsRef.begin(), arrFontsRef.end(), fontID.num) != arrFontsRef.end()) + continue; + + Object oObj, oField, oFont; + pField->getFieldRef(&oObj); + oObj.fetch(xref, &oField); + oObj.free(); + + bool bFindResources = false; + if (oField.dictLookup("DR", &oObj)->isDict() && oObj.dictLookup("Font", &oFont)->isDict()) + { + for (int i = 0; i < oFont.dictGetLength(); ++i) + { + Object oFontRef; + if (oFont.dictGetValNF(i, &oFontRef)->isRef() && oFontRef.getRef() == fontID) + { + bFindResources = true; + oFontRef.free(); + break; + } + oFontRef.free(); + } + } + oFont.free(); oField.free(); + + if (!bFindResources) + { + oObj.free(); + Object* oAcroForm = pAcroForms->getAcroFormObj(); + if (oAcroForm->isDict() && oAcroForm->dictLookup("DR", &oObj)->isDict() && oObj.dictLookup("Font", &oFont)->isDict()) + { + for (int i = 0; i < oFont.dictGetLength(); ++i) + { + Object oFontRef; + if (oFont.dictGetValNF(i, &oFontRef)->isRef() && oFontRef.getRef() == fontID) + { + bFindResources = true; + oFontRef.free(); + break; + } + oFontRef.free(); + } + } + oFont.free(); + } + + GfxFont* gfxFont = NULL; + GfxFontDict *gfxFontDict = NULL; + if (bFindResources) + { + Object oFontRef; + if (oObj.dictLookupNF("Font", &oFontRef)->isRef()) + { + if (oFontRef.fetch(xref, &oFont)->isDict()) + { + Ref r = oFontRef.getRef(); + gfxFontDict = new GfxFontDict(xref, &r, oFont.getDict()); + gfxFont = gfxFontDict->lookupByRef(fontID); + } + oFont.free(); + } + else if (oFontRef.isDict()) + { + gfxFontDict = new GfxFontDict(xref, NULL, oFontRef.getDict()); + gfxFont = gfxFontDict->lookupByRef(fontID); + } + oFontRef.free(); + } + oObj.free(); + + std::wstring wsFileName, wsFontName; + if (gfxFont) + GetFont(xref, m_pFontManager, m_pFontList, gfxFont, wsFileName, wsFontName); + + if (wsFileName.length() > 17 && wsFileName.substr(0, 17) == L"storage_internal_") + { + std::string sFileName = U_TO_UTF8(wsFileName); + oRes.WriteString(sFileName); + nFontsID++; + arrFontsRef.push_back(fontID.num); + } + + RELEASEOBJECT(gfxFontDict); + } + + oRes.AddInt(nFontsID, nFontsPos); + + oRes.WriteLen(); + BYTE* bRes = oRes.GetBuffer(); + oRes.ClearWithoutAttack(); + return bRes; +} BYTE* CPdfReader::VerifySign(const std::wstring& sFile, ICertificate* pCertificate, int nWidget) { if (!m_pPDFDocument || !m_pPDFDocument->getCatalog()) diff --git a/PdfFile/PdfReader.h b/PdfFile/PdfReader.h index 9618d7eebb..76c155273b 100644 --- a/PdfFile/PdfReader.h +++ b/PdfFile/PdfReader.h @@ -73,6 +73,7 @@ public: BYTE* GetStructure(); BYTE* GetLinks(int nPageIndex); BYTE* GetWidgets(); + BYTE* GetWidgetFonts(); BYTE* GetAnnots(int nPageIndex = -1); BYTE* VerifySign(const std::wstring& sFile, ICertificate* pCertificate, int nWidget = -1); BYTE* GetAPWidget (int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, int nWidget = -1, const char* sView = NULL, const char* sBView = NULL); diff --git a/PdfFile/SrcReader/RendererOutputDev.cpp b/PdfFile/SrcReader/RendererOutputDev.cpp index a3de60e047..6478188575 100644 --- a/PdfFile/SrcReader/RendererOutputDev.cpp +++ b/PdfFile/SrcReader/RendererOutputDev.cpp @@ -1336,6 +1336,7 @@ namespace PdfReader // StemV oFontDescriptor.dictLookup("StemV", &oDictItem); + if (oDictItem.isInt()) oFontSelect.usWeight = new USHORT(sqrt(abs(oDictItem.getNum() - 50.5)) * 65); oDictItem.free(); // StemH diff --git a/X2tConverter/src/ASCConverters.cpp b/X2tConverter/src/ASCConverters.cpp index 215f3c336e..e35d284e38 100644 --- a/X2tConverter/src/ASCConverters.cpp +++ b/X2tConverter/src/ASCConverters.cpp @@ -529,6 +529,14 @@ namespace NExtractTools nRes = apply_changes(sFrom, sTo, NSDoctRenderer::DoctRendererFormat::FormatFile::DOCT, sDocxFile, params, convertParams); } nRes = zip2dir(sDocxFile, sDocxDir); + + if (false == SUCCEEDED_X2T(nRes)) + { + if (NSDirectory::GetFilesCount(sDocxDir, true) > 3) + { + nRes = 0; + } + } } else if (AVS_OFFICESTUDIO_FILE_DOCUMENT_DOCM == nFormatFrom) { @@ -541,6 +549,13 @@ namespace NExtractTools { nRes = zip2dir(sFrom, sDocxDir); } + if (false == SUCCEEDED_X2T(nRes)) + { + if (NSDirectory::GetFilesCount(sDocxDir, true) > 3) + { + nRes = 0; + } + } } else if (AVS_OFFICESTUDIO_FILE_DOCUMENT_DOTX == nFormatFrom) { diff --git a/X2tConverter/test/ExampleFiles/xlsb2xlsx/simple1.xlsb b/X2tConverter/test/ExampleFiles/xlsb2xlsx/simple1.xlsb deleted file mode 100644 index c71a49e25f..0000000000 Binary files a/X2tConverter/test/ExampleFiles/xlsb2xlsx/simple1.xlsb and /dev/null differ diff --git a/X2tConverter/test/ExampleFiles/xlsb2xlsx/simple1.xlsx b/X2tConverter/test/ExampleFiles/xlsb2xlsx/simple1.xlsx deleted file mode 100644 index 6f10ff38a5..0000000000 Binary files a/X2tConverter/test/ExampleFiles/xlsb2xlsx/simple1.xlsx and /dev/null differ diff --git a/X2tConverter/test/ExampleFiles/xlsb2xlsx/simple2.xlsb b/X2tConverter/test/ExampleFiles/xlsb2xlsx/simple2.xlsb deleted file mode 100644 index b6e5e04031..0000000000 Binary files a/X2tConverter/test/ExampleFiles/xlsb2xlsx/simple2.xlsb and /dev/null differ diff --git a/X2tConverter/test/ExampleFiles/xlsb2xlsx/simple2.xlsx b/X2tConverter/test/ExampleFiles/xlsb2xlsx/simple2.xlsx deleted file mode 100644 index e49f4060d7..0000000000 Binary files a/X2tConverter/test/ExampleFiles/xlsb2xlsx/simple2.xlsx and /dev/null differ diff --git a/X2tConverter/test/qmake/common.cpp b/X2tConverter/test/qmake/common.cpp deleted file mode 100644 index cd7b3bba23..0000000000 --- a/X2tConverter/test/qmake/common.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* - * (c) Copyright Ascensio System SIA 2010-2023 - * - * This program is a free software product. You can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License (AGPL) - * version 3 as published by the Free Software Foundation. In accordance with - * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect - * that Ascensio System SIA expressly excludes the warranty of non-infringement - * of any third-party rights. - * - * This program is distributed WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For - * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html - * - * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish - * street, Riga, Latvia, EU, LV-1050. - * - * The interactive user interfaces in modified source and object code versions - * of the Program must display Appropriate Legal Notices, as required under - * Section 5 of the GNU AGPL version 3. - * - * Pursuant to Section 7(b) of the License you must retain the original Product - * logo when distributing the program. Pursuant to Section 7(e) we decline to - * grant you any rights under trademark law for use of our trademarks. - * - * All the Product's GUI elements, including illustrations and icon sets, as - * well as technical writing content are licensed under the terms of the - * Creative Commons Attribution-ShareAlike 4.0 International. See the License - * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode - * - */ - -#include "common.h" - -#include "../../../DesktopEditor/common/Directory.h" -#include "../../../DesktopEditor/common/Path.h" -#include "../../../OfficeUtils/src/OfficeUtils.h" -#include "../../../DesktopEditor/fontengine/ApplicationFontsWorker.h" -#include "../../../Common/OfficeFileFormatChecker.h" -#include "../../../DesktopEditor/common/StringBuilder.h" -#include "../../src/dylib/x2t.h" -#include "tchar.h" -#include -#include -#include -#include - - -std::wstring GetWorkDir() -{ - std::wstring curDir = NSFile::GetProcessDirectory(); - return NSDirectory::CreateDirectoryWithUniqueName(curDir); -} - -void RemoveWorkDir(const std::wstring &dir) -{ - NSDirectory::DeleteDirectory(dir); -} - -int ConvertFile(const std::wstring &fileName) -{ - x2tchar* args[2]; - args[0] = NULL; - args[1] = (x2tchar*)fileName.c_str(); - - int nResultCode = X2T_Convert(2, args); - return nResultCode; -} - -void PrepareFiles(const std::wstring &fileName, const std::wstring &exampleFileName, const std::wstring &tempDirName) -{ - std::wstring sTempUnpackedXLSB = tempDirName + FILE_SEPARATOR_STR + _T("result_unpacked"); - NSDirectory::CreateDirectory(sTempUnpackedXLSB); - COfficeUtils oCOfficeUtils(NULL); - _UINT32 nRes = oCOfficeUtils.ExtractToDirectory(fileName, sTempUnpackedXLSB, NULL, 0); - - std::wstring sTempUnpackedXLSX = tempDirName + FILE_SEPARATOR_STR + _T("example_unpacked"); - NSDirectory::CreateDirectory(sTempUnpackedXLSX); - nRes = oCOfficeUtils.ExtractToDirectory(exampleFileName, sTempUnpackedXLSX, NULL, 0); -} - -void CheckFonts(const std::wstring& fontsDir, bool isUseSystem, const std::vector& addtitionalFontsDirs) -{ - CApplicationFontsWorker fonts_worker; - - fonts_worker.m_sDirectory = fontsDir; - if (!NSDirectory::Exists(fonts_worker.m_sDirectory)) - NSDirectory::CreateDirectory(fonts_worker.m_sDirectory); - - fonts_worker.m_bIsUseSystemFonts = isUseSystem; - - for (const auto& additional : addtitionalFontsDirs) - { - std::wstring sFolder = additional; - if (0 == sFolder.find(L".")) - sFolder = NSFile::GetProcessDirectory() + FILE_SEPARATOR_STR + sFolder; - fonts_worker.m_arAdditionalFolders.push_back(sFolder); - } - - fonts_worker.m_bIsNeedThumbnails = false; - NSFonts::IApplicationFonts* pFonts = fonts_worker.Check(); - RELEASEINTERFACE(pFonts); -} -std::wstring CreateParamsFile(const std::wstring &pathFrom, const std::wstring &pathTo, const std::wstring &FontsDir, const std::wstring &TempDir) -{ - NSStringUtils::CStringBuilder oBuilder; - - oBuilder.WriteString(L""); - oBuilder.WriteString(L""); - - // main - oBuilder.WriteString(L""); - oBuilder.WriteEncodeXmlString(pathFrom); - oBuilder.WriteString(L""); - - oBuilder.WriteString(L""); - oBuilder.WriteEncodeXmlString(pathTo); - oBuilder.WriteString(L""); - - oBuilder.WriteString(L""); - int nFormat = COfficeFileFormatChecker::GetFormatByExtension(L"." + NSFile::GetFileExtention(pathTo)); - oBuilder.WriteString(std::to_wstring(nFormat)); - oBuilder.WriteString(L""); - - if (nFormat == AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDFA) - oBuilder.WriteString(L"true"); - - oBuilder.WriteString(L""); - oBuilder.WriteEncodeXmlString(L"/sdkjs/slide/themes"); - oBuilder.WriteString(L""); - - // changes - oBuilder.WriteString(L"false"); - - oBuilder.WriteString(L"true"); - - // fonts - oBuilder.WriteString(L""); - oBuilder.WriteEncodeXmlString(FontsDir); - oBuilder.WriteString(L""); - - oBuilder.WriteString(L""); - oBuilder.WriteString(FontsDir + L"/AllFonts.js"); - oBuilder.WriteString(L""); - - // temp directory - oBuilder.WriteString(L""); - oBuilder.WriteEncodeXmlString(TempDir); - oBuilder.WriteString(L""); - - - // txt/csv - oBuilder.WriteString(L""); - oBuilder.WriteEncodeXmlString(L"46"); - oBuilder.WriteString(L""); - - oBuilder.WriteString(L""); - oBuilder.WriteEncodeXmlString(L"4"); - oBuilder.WriteString(L""); - - oBuilder.WriteString(L""); - - auto xml = TempDir + FILE_SEPARATOR_STR + L"params.xml"; - // writing xml data into file - if(NSFile::CFileBinary::Exists(xml)) - NSFile::CFileBinary::Remove(xml); - - NSFile::CFileBinary xml_file; - xml_file.CreateFile(xml); - xml_file.WriteStringUTF8(oBuilder.GetData()); - xml_file.CloseFile(); - - return xml; -} - diff --git a/X2tConverter/test/qmake/common.h b/X2tConverter/test/qmake/common.h deleted file mode 100644 index 6fbc0dfda5..0000000000 --- a/X2tConverter/test/qmake/common.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * (c) Copyright Ascensio System SIA 2010-2023 - * - * This program is a free software product. You can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License (AGPL) - * version 3 as published by the Free Software Foundation. In accordance with - * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect - * that Ascensio System SIA expressly excludes the warranty of non-infringement - * of any third-party rights. - * - * This program is distributed WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For - * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html - * - * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish - * street, Riga, Latvia, EU, LV-1050. - * - * The interactive user interfaces in modified source and object code versions - * of the Program must display Appropriate Legal Notices, as required under - * Section 5 of the GNU AGPL version 3. - * - * Pursuant to Section 7(b) of the License you must retain the original Product - * logo when distributing the program. Pursuant to Section 7(e) we decline to - * grant you any rights under trademark law for use of our trademarks. - * - * All the Product's GUI elements, including illustrations and icon sets, as - * well as technical writing content are licensed under the terms of the - * Creative Commons Attribution-ShareAlike 4.0 International. See the License - * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode - * - */ -#include "../../../OOXML/Base/Base.h" -#include -#include - -void PrepareFiles(const std::wstring &fileName, const std::wstring &exampleFileName, const std::wstring &tempDirName); -int ConvertFile(const std::wstring &fileName); -std::wstring GetWorkDir(); -void RemoveWorkDir(const std::wstring &dir); -std::wstring CreateParamsFile(const std::wstring &pathFrom, const std::wstring &pathTo, const std::wstring &FontsDir, const std::wstring &TempDir); -void CheckFonts(const std::wstring& fontsDir, bool isUseSystem = true, const std::vector& addtitionalFontsDirs = {}); - diff --git a/X2tConverter/test/qmake/main.cpp b/X2tConverter/test/qmake/main.cpp index 914a3a04e9..c1ff84e987 100644 --- a/X2tConverter/test/qmake/main.cpp +++ b/X2tConverter/test/qmake/main.cpp @@ -3,12 +3,175 @@ #include "../../../DesktopEditor/fontengine/ApplicationFontsWorker.h" #include "../../../Common/OfficeFileFormatChecker.h" #include "../../src/dylib/x2t.h" -#include "common.h" -#include +void CheckFonts(const std::wstring& fontsDir, bool isUseSystem = true, const std::vector& addtitionalFontsDirs = {}) +{ + CApplicationFontsWorker fonts_worker; + + fonts_worker.m_sDirectory = fontsDir; + if (!NSDirectory::Exists(fonts_worker.m_sDirectory)) + NSDirectory::CreateDirectory(fonts_worker.m_sDirectory); + + fonts_worker.m_bIsUseSystemFonts = isUseSystem; + + for (const auto& additional : addtitionalFontsDirs) + { + std::wstring sFolder = additional; + if (0 == sFolder.find(L".")) + sFolder = NSFile::GetProcessDirectory() + FILE_SEPARATOR_STR + sFolder; + fonts_worker.m_arAdditionalFolders.push_back(sFolder); + } + + fonts_worker.m_bIsNeedThumbnails = false; + NSFonts::IApplicationFonts* pFonts = fonts_worker.Check(); + RELEASEINTERFACE(pFonts); +} + +#define UNUSED_PARAM(x) (void)x int main(int argc, char** argv) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); +{ + // warnings + UNUSED_PARAM(argc); + UNUSED_PARAM(argv); + + std::wstring curr_dir = NSFile::GetProcessDirectory(); + std::wstring wsep = FILE_SEPARATOR_STR; + + std::wstring filename_in = curr_dir + wsep + L"123.docx"; + std::wstring filename_out = curr_dir + wsep + L"123.pdf"; + std::wstring fonts_dir = curr_dir + wsep + L"fonts"; + std::wstring xml = curr_dir + wsep + L"params.xml"; + + std::wstring tmp_dir = NSDirectory::CreateDirectoryWithUniqueName(curr_dir); + + CheckFonts(fonts_dir); + + // GENERATE XML + NSStringUtils::CStringBuilder oBuilder; + + oBuilder.WriteString(L""); + oBuilder.WriteString(L""); + + // main + oBuilder.WriteString(L""); + oBuilder.WriteEncodeXmlString(filename_in); + oBuilder.WriteString(L""); + + oBuilder.WriteString(L""); + oBuilder.WriteEncodeXmlString(filename_out); + oBuilder.WriteString(L""); + + oBuilder.WriteString(L""); + int nFormat = COfficeFileFormatChecker::GetFormatByExtension(L"." + NSFile::GetFileExtention(filename_out)); + oBuilder.WriteString(std::to_wstring(nFormat)); + oBuilder.WriteString(L""); + + if (nFormat == AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDFA) + oBuilder.WriteString(L"true"); + + oBuilder.WriteString(L""); + oBuilder.WriteEncodeXmlString(curr_dir + L"/sdkjs/slide/themes"); + oBuilder.WriteString(L""); + + // changes + oBuilder.WriteString(L"false"); + + oBuilder.WriteString(L"true"); + + // fonts + oBuilder.WriteString(L""); + oBuilder.WriteEncodeXmlString(fonts_dir); + oBuilder.WriteString(L""); + + oBuilder.WriteString(L""); + oBuilder.WriteString(fonts_dir + L"/AllFonts.js"); + oBuilder.WriteString(L""); + + // temp directory + oBuilder.WriteString(L""); + oBuilder.WriteEncodeXmlString(tmp_dir); + oBuilder.WriteString(L""); + + // encrypt + if (false) + { + oBuilder.WriteString(L""); + oBuilder.WriteEncodeXmlString(L"111"); + oBuilder.WriteString(L""); + + oBuilder.WriteString(L""); + oBuilder.WriteEncodeXmlString(L"222"); + oBuilder.WriteString(L""); + } + + // docinfo (private rooms) + if (false) + { + oBuilder.WriteString(L""); + oBuilder.WriteEncodeXmlString(L"{data}"); + oBuilder.WriteString(L""); + } + + // txt/csv + oBuilder.WriteString(L""); + oBuilder.WriteEncodeXmlString(L"46"); + oBuilder.WriteString(L""); + + oBuilder.WriteString(L""); + oBuilder.WriteEncodeXmlString(L"4"); + oBuilder.WriteString(L""); + + // js params + if (false) + { + oBuilder.WriteString(L""); + oBuilder.WriteString(L"{"); + // * + oBuilder.WriteString(L"}"); + oBuilder.WriteString(L""); + } + + if (false) + { + // if need disable js engine cache + oBuilder.WriteString(L"1"); + } + + // images + if (true && (0 != (nFormat & AVS_OFFICESTUDIO_FILE_IMAGE))) + { + oBuilder.WriteString(L"false"); + + if (nFormat == AVS_OFFICESTUDIO_FILE_IMAGE_JPG) + oBuilder.WriteString(L"3"); + + oBuilder.WriteString(L""); + } + + oBuilder.WriteString(L""); + + // writing xml data into file + if(NSFile::CFileBinary::Exists(xml)) + NSFile::CFileBinary::Remove(xml); + + NSFile::CFileBinary xml_file; + xml_file.CreateFile(xml); + xml_file.WriteStringUTF8(oBuilder.GetData()); + xml_file.CloseFile(); + +#if !defined(_WIN32) && !defined (_WIN64) + std::string xmlDst = U_TO_UTF8(xml); +#else + std::wstring xmlDst = xml; +#endif + + x2tchar* args[2]; + args[0] = NULL; + args[1] = (x2tchar*)xmlDst.c_str(); + + int nResultCode = X2T_Convert(2, args); + NSDirectory::DeleteDirectory(tmp_dir); + + return nResultCode; } diff --git a/X2tConverter/test/qmake/test.pro b/X2tConverter/test/qmake/test.pro index 05dd063e8c..d69cfe9b54 100644 --- a/X2tConverter/test/qmake/test.pro +++ b/X2tConverter/test/qmake/test.pro @@ -7,18 +7,10 @@ DEFINES += BUILD_X2T_AS_LIBRARY_DYLIB X2T_DIR = $$PWD/../.. include($$X2T_DIR/build/Qt/X2tConverter.pri) -include($$X2T_DIR/../Common/3dParty/googletest/googletest.pri) HEADERS += $$X2T_DIR/src/dylib/x2t.h SOURCES += $$X2T_DIR/src/dylib/x2t.cpp -SOURCES += main.cpp\ - common.cpp\ - ../xlsb2xlsx/conversion.cpp - -HEADERS += common.h +SOURCES += main.cpp DESTDIR = $$CORE_BUILDS_BINARY_PATH - - -SOURCES -= $$CORE_GTEST_PATH/src/gtest_main.cc diff --git a/X2tConverter/test/xlsb2xlsx/conversion.cpp b/X2tConverter/test/xlsb2xlsx/conversion.cpp deleted file mode 100644 index b7c64757c8..0000000000 --- a/X2tConverter/test/xlsb2xlsx/conversion.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/* - * (c) Copyright Ascensio System SIA 2010-2023 - * - * This program is a free software product. You can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License (AGPL) - * version 3 as published by the Free Software Foundation. In accordance with - * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect - * that Ascensio System SIA expressly excludes the warranty of non-infringement - * of any third-party rights. - * - * This program is distributed WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For - * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html - * - * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish - * street, Riga, Latvia, EU, LV-1050. - * - * The interactive user interfaces in modified source and object code versions - * of the Program must display Appropriate Legal Notices, as required under - * Section 5 of the GNU AGPL version 3. - * - * Pursuant to Section 7(b) of the License you must retain the original Product - * logo when distributing the program. Pursuant to Section 7(e) we decline to - * grant you any rights under trademark law for use of our trademarks. - * - * All the Product's GUI elements, including illustrations and icon sets, as - * well as technical writing content are licensed under the terms of the - * Creative Commons Attribution-ShareAlike 4.0 International. See the License - * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode - * - */ - -#include "../qmake/common.h" -#include -#include -#include -#include "gtest/gtest.h" - -void processTestFile(const std::wstring &tempDir, const std::wstring &testFile, const std::wstring &resultFile, const std::wstring &exampleFile) -{ - auto fontsDir = tempDir + FILE_SEPARATOR_STR + L"fonst"; - boost::filesystem::path rootPath = std::wstring{L".."} + FILE_SEPARATOR_STR; - rootPath =boost::filesystem::absolute(rootPath.wstring() + rootPath.wstring() + rootPath.wstring()+ rootPath.wstring()); - boost::filesystem::path filePath = rootPath.wstring() +L"X2tConverter" + FILE_SEPARATOR_STR + L"test" + FILE_SEPARATOR_STR +L"ExampleFiles" - + FILE_SEPARATOR_STR + L"xlsb2xlsx" + FILE_SEPARATOR_STR + testFile; - boost::filesystem::path examplePath = rootPath.wstring() +L"X2tConverter" + FILE_SEPARATOR_STR + L"test" + FILE_SEPARATOR_STR +L"ExampleFiles" - + FILE_SEPARATOR_STR + L"xlsb2xlsx" + FILE_SEPARATOR_STR + exampleFile; - - std::wstring resultPath = tempDir + FILE_SEPARATOR_STR + resultFile; - CheckFonts(fontsDir); - - auto paramsPath = CreateParamsFile(filePath.wstring(), resultPath, fontsDir, tempDir); - ConvertFile(paramsPath); - PrepareFiles(resultPath, examplePath.wstring(), tempDir); -} - -class SimpleTests1 : public ::testing::Test -{ -public: - - static void SetUpTestCase() - { - - tempDir = GetWorkDir(); - processTestFile(tempDir, L"simple1.xlsb", L"result.xlsx", L"simple1.xlsx"); - } - - - static void TearDownTestCase() - { - RemoveWorkDir(tempDir); - } - - static std::wstring tempDir; -}; -class SimpleTests2 : public ::testing::Test -{ -public: - - static void SetUpTestCase() - { - - tempDir = GetWorkDir(); - processTestFile(tempDir, L"simple2.xlsb", L"result.xlsx", L"simple2.xlsx"); - } - - - static void TearDownTestCase() - { - RemoveWorkDir(tempDir); - } - - static std::wstring tempDir; -}; - -std::wstring SimpleTests1::tempDir = L""; -std::wstring SimpleTests2::tempDir = L""; - -_UINT32 readFiles(const std::wstring &filePath, const std::wstring &examplePath, std::wstring &fileContent, std::wstring &exampleContent ) -{ - - boost::filesystem::path path1(filePath); - boost::filesystem::path path2(examplePath); - path1 = boost::filesystem::absolute(path1); - path2 = boost::filesystem::absolute(path2); - std::ifstream file1(path1.string()); - std::ifstream file2(path2.string()); - - if (!file1.is_open() || !file2.is_open()) - { - return 1; - } - fileContent = std::wstring((std::istreambuf_iterator(file1)), std::istreambuf_iterator()); - exampleContent = std::wstring((std::istreambuf_iterator(file2)), std::istreambuf_iterator()); - - return 0; -} - - - -TEST_F(SimpleTests1, ContentTypesTest) -{ - auto tempDir = SimpleTests1::tempDir; - std::wstring path1(tempDir + FILE_SEPARATOR_STR + L"result_unpacked"+ FILE_SEPARATOR_STR + L"[Content_Types].xml"); - std::wstring path2(tempDir + FILE_SEPARATOR_STR + L"example_unpacked"+ FILE_SEPARATOR_STR + L"[Content_Types].xml"); - std::wstring content1; - std::wstring content2; - ASSERT_EQ(readFiles(path1, path2, content1, content2), 0); - ASSERT_TRUE(boost::algorithm::equals(content1, content2)); -} - -TEST_F(SimpleTests1, WorkbookTest) -{ - auto tempDir = SimpleTests1::tempDir; - std::wstring path1(tempDir + FILE_SEPARATOR_STR + L"result_unpacked"+ FILE_SEPARATOR_STR + L"xl" + - FILE_SEPARATOR_STR + L"workbook.xml"); - std::wstring path2(tempDir + FILE_SEPARATOR_STR +L"example_unpacked"+ FILE_SEPARATOR_STR + L"xl" + - FILE_SEPARATOR_STR + L"workbook.xml"); - std::wstring content1; - std::wstring content2; - ASSERT_EQ(readFiles(path1, path2, content1, content2), 0); - ASSERT_TRUE(boost::algorithm::equals(content1, content2)); -} - -TEST_F(SimpleTests1, StylesTest) -{ - auto tempDir = SimpleTests1::tempDir; - std::wstring path1(tempDir + FILE_SEPARATOR_STR + L"result_unpacked"+ FILE_SEPARATOR_STR + L"xl" + - FILE_SEPARATOR_STR + L"styles.xml"); - std::wstring path2(tempDir + FILE_SEPARATOR_STR +L"example_unpacked"+ FILE_SEPARATOR_STR + L"xl" + - FILE_SEPARATOR_STR + L"styles.xml"); - std::wstring content1; - std::wstring content2; - ASSERT_EQ(readFiles(path1, path2, content1, content2), 0); - ASSERT_TRUE(boost::algorithm::equals(content1, content2)); -} - -TEST_F(SimpleTests1, SharedStringsTest) -{ - auto tempDir = SimpleTests1::tempDir; - std::wstring path1(tempDir + FILE_SEPARATOR_STR + L"result_unpacked"+ FILE_SEPARATOR_STR + L"xl" + - FILE_SEPARATOR_STR + L"sharedStrings.xml"); - std::wstring path2(tempDir + FILE_SEPARATOR_STR +L"example_unpacked"+ FILE_SEPARATOR_STR + L"xl" + - FILE_SEPARATOR_STR + L"sharedStrings.xml"); - std::wstring content1; - std::wstring content2; - ASSERT_EQ(readFiles(path1, path2, content1, content2), 0); - ASSERT_TRUE(boost::algorithm::equals(content1, content2)); -} - -TEST_F(SimpleTests1, WorksheetsTest) -{ - auto tempDir = SimpleTests1::tempDir; - std::wstring path1(tempDir + FILE_SEPARATOR_STR + L"result_unpacked"+ FILE_SEPARATOR_STR + L"xl" + - FILE_SEPARATOR_STR + L"worksheets" + FILE_SEPARATOR_STR + L"sheet1.xml"); - std::wstring path2(tempDir + FILE_SEPARATOR_STR +L"example_unpacked"+ FILE_SEPARATOR_STR + L"xl" + - FILE_SEPARATOR_STR + L"worksheets" + FILE_SEPARATOR_STR + L"sheet1.xml"); - std::wstring content1; - std::wstring content2; - ASSERT_EQ(readFiles(path1, path2, content1, content2), 0); - ASSERT_TRUE(boost::algorithm::equals(content1, content2)); -} - -TEST_F(SimpleTests2, ContentTypesTest) -{ - auto tempDir = SimpleTests2::tempDir; - std::wstring path1(tempDir + FILE_SEPARATOR_STR + L"result_unpacked"+ FILE_SEPARATOR_STR + L"[Content_Types].xml"); - std::wstring path2(tempDir + FILE_SEPARATOR_STR + L"example_unpacked"+ FILE_SEPARATOR_STR + L"[Content_Types].xml"); - std::wstring content1; - std::wstring content2; - ASSERT_EQ(readFiles(path1, path2, content1, content2), 0); - ASSERT_TRUE(boost::algorithm::equals(content1, content2)); -} - -TEST_F(SimpleTests2, WorkbookTest) -{ - auto tempDir = SimpleTests2::tempDir; - std::wstring path1(tempDir + FILE_SEPARATOR_STR + L"result_unpacked"+ FILE_SEPARATOR_STR + L"xl" + - FILE_SEPARATOR_STR + L"workbook.xml"); - std::wstring path2(tempDir + FILE_SEPARATOR_STR +L"example_unpacked"+ FILE_SEPARATOR_STR + L"xl" + - FILE_SEPARATOR_STR + L"workbook.xml"); - std::wstring content1; - std::wstring content2; - ASSERT_EQ(readFiles(path1, path2, content1, content2), 0); - ASSERT_TRUE(boost::algorithm::equals(content1, content2)); -} - -TEST_F(SimpleTests2, StylesTest) -{ - auto tempDir = SimpleTests2::tempDir; - std::wstring path1(tempDir + FILE_SEPARATOR_STR + L"result_unpacked"+ FILE_SEPARATOR_STR + L"xl" + - FILE_SEPARATOR_STR + L"styles.xml"); - std::wstring path2(tempDir + FILE_SEPARATOR_STR +L"example_unpacked"+ FILE_SEPARATOR_STR + L"xl" + - FILE_SEPARATOR_STR + L"styles.xml"); - std::wstring content1; - std::wstring content2; - ASSERT_EQ(readFiles(path1, path2, content1, content2), 0); - ASSERT_TRUE(boost::algorithm::equals(content1, content2)); -} - -TEST_F(SimpleTests2, SharedStringsTest) -{ - auto tempDir = SimpleTests2::tempDir; - std::wstring path1(tempDir + FILE_SEPARATOR_STR + L"result_unpacked"+ FILE_SEPARATOR_STR + L"xl" + - FILE_SEPARATOR_STR + L"sharedStrings.xml"); - std::wstring path2(tempDir + FILE_SEPARATOR_STR +L"example_unpacked"+ FILE_SEPARATOR_STR + L"xl" + - FILE_SEPARATOR_STR + L"sharedStrings.xml"); - std::wstring content1; - std::wstring content2; - ASSERT_EQ(readFiles(path1, path2, content1, content2), 0); - ASSERT_TRUE(boost::algorithm::equals(content1, content2)); -} - -TEST_F(SimpleTests2, WorksheetsTest) -{ - auto tempDir = SimpleTests2::tempDir; - std::wstring path1(tempDir + FILE_SEPARATOR_STR + L"result_unpacked"+ FILE_SEPARATOR_STR + L"xl" + - FILE_SEPARATOR_STR + L"worksheets" + FILE_SEPARATOR_STR + L"sheet1.xml"); - std::wstring path2(tempDir + FILE_SEPARATOR_STR +L"example_unpacked"+ FILE_SEPARATOR_STR + L"xl" + - FILE_SEPARATOR_STR + L"worksheets" + FILE_SEPARATOR_STR + L"sheet1.xml"); - std::wstring content1; - std::wstring content2; - ASSERT_EQ(readFiles(path1, path2, content1, content2), 0); - ASSERT_TRUE(boost::algorithm::equals(content1, content2)); -} -