diff --git a/Common/Network/FileTransporter/src/manager.cpp b/Common/Network/FileTransporter/src/manager.cpp index 78aa9cd01f..834a114f09 100644 --- a/Common/Network/FileTransporter/src/manager.cpp +++ b/Common/Network/FileTransporter/src/manager.cpp @@ -32,8 +32,8 @@ #include #include "./../include/manager.h" -#include "./../../../core/DesktopEditor/graphics/TemporaryCS.h" -#include "./../../../core/DesktopEditor/graphics/BaseThread.h" +#include "./../../../../DesktopEditor/graphics/TemporaryCS.h" +#include "./../../../../DesktopEditor/graphics/BaseThread.h" namespace ASC { diff --git a/DesktopEditor/agg-2.4/include/agg_alpha_mask_u8.h b/DesktopEditor/agg-2.4/include/agg_alpha_mask_u8.h index eee19400e3..78148e221e 100644 --- a/DesktopEditor/agg-2.4/include/agg_alpha_mask_u8.h +++ b/DesktopEditor/agg-2.4/include/agg_alpha_mask_u8.h @@ -31,12 +31,6 @@ namespace agg static unsigned calculate(const int8u* p) { return *p; } }; - //===================================================four_component_mask_u8 - struct four_component_mask_u8 - { - static unsigned calculate(const int8u* p) { return p[3]; } - }; - //=====================================================rgb_to_gray_mask_u8 template diff --git a/DesktopEditor/common/StringUTF32.cpp b/DesktopEditor/common/StringUTF32.cpp index 3f745a2b6c..d98ad05d70 100644 --- a/DesktopEditor/common/StringUTF32.cpp +++ b/DesktopEditor/common/StringUTF32.cpp @@ -30,125 +30,148 @@ * */ #include "StringUTF32.h" +#include "StringExt.h" using namespace std; using namespace NSStringUtils; -CStringUTF32::CStringUTF32() {} -CStringUTF32::CStringUTF32(const CStringUTF32 &other): m_vec(other.m_vec) {} -CStringUTF32::CStringUTF32(const wchar_t *other) { *this = other; } -CStringUTF32::CStringUTF32(const wstring &other) { *this = other; } -CStringUTF32::CStringUTF32(const vector &other): m_vec(other) {} +CStringUTF32::CStringUTF32() +{ +} +CStringUTF32::CStringUTF32(const CStringUTF32& other) : m_vec(other.m_vec) +{ +} +CStringUTF32::CStringUTF32(const wchar_t* other) +{ + *this = other; +} +CStringUTF32::CStringUTF32(const wstring& other) +{ + *this = other; +} +CStringUTF32::CStringUTF32(const vector& other) : m_vec(other) +{ +} CStringUTF32::CStringUTF32(const uint32_t* data, const size_t& len) { - m_vec.reserve(len); - for (size_t i = 0; i < len; ++i) - this->m_vec.push_back(data[i]); + m_vec.reserve(len); + for (size_t i = 0; i < len; ++i) + this->m_vec.push_back(data[i]); } -CStringUTF32::~CStringUTF32() {} +CStringUTF32::~CStringUTF32() +{ +} bool CStringUTF32::empty() const { - return this->m_vec.empty(); + return this->m_vec.empty(); } size_t CStringUTF32::length() const { - return this->m_vec.size(); + return this->m_vec.size(); } wstring CStringUTF32::ToStdWString() const { - if (0 == length()) - return L""; - return NSStringExt::CConverter::GetUnicodeFromUTF32(&this->m_vec[0], static_cast(this->length())); + if (0 == length()) + return L""; + return NSStringExt::CConverter::GetUnicodeFromUTF32(&this->m_vec[0], static_cast(this->length())); } -bool CStringUTF32::operator == (const CStringUTF32 &right) const +bool CStringUTF32::operator==(const CStringUTF32& right) const { - return this->m_vec == right.m_vec; + return this->m_vec == right.m_vec; } -bool CStringUTF32::operator != (const CStringUTF32 &right) const +bool CStringUTF32::operator!=(const CStringUTF32& right) const { - return !(this->m_vec == right.m_vec); + return !(this->m_vec == right.m_vec); } -uint32_t& CStringUTF32::operator [] (size_t index) +uint32_t& CStringUTF32::operator[](size_t index) { - return this->m_vec[index]; + return this->m_vec[index]; } -CStringUTF32& CStringUTF32::operator = (const CStringUTF32 &right) +CStringUTF32& CStringUTF32::operator=(const CStringUTF32& right) { - this->m_vec = right.m_vec; - return *this; + this->m_vec = right.m_vec; + return *this; } -CStringUTF32& CStringUTF32::operator = (const wchar_t *right) +CStringUTF32& CStringUTF32::operator=(const wchar_t* right) { - if (!right) - { - m_vec.clear(); - return *this; - } + if (!right) + { + m_vec.clear(); + return *this; + } - return (*this = std::wstring(right)); + return (*this = std::wstring(right)); } -CStringUTF32& CStringUTF32::operator = (const wstring &right) +CStringUTF32& CStringUTF32::operator=(const wstring& right) { - if (right.empty()) - { - m_vec.clear(); - return *this; - } + if (right.empty()) + { + m_vec.clear(); + return *this; + } - unsigned int utf32_len = 0; - unsigned int* utf32 = NSStringExt::CConverter::GetUtf32FromUnicode(right, utf32_len); - this->m_vec.clear(); - this->m_vec.reserve(utf32_len); - for (size_t i = 0; i < utf32_len; ++i) - this->m_vec.push_back(utf32[i]); + unsigned int utf32_len = 0; + unsigned int* utf32 = NSStringExt::CConverter::GetUtf32FromUnicode(right, utf32_len); + this->m_vec.clear(); + this->m_vec.reserve(utf32_len); + for (size_t i = 0; i < utf32_len; ++i) + this->m_vec.push_back(utf32[i]); - delete [] utf32; - return *this; + delete[] utf32; + return *this; } -CStringUTF32& CStringUTF32::operator = (const std::vector &right) +CStringUTF32& CStringUTF32::operator=(const std::vector& right) { - this->m_vec = right; - return *this; + this->m_vec = right; + return *this; } - -CStringUTF32 CStringUTF32::operator + (const CStringUTF32 &right) const +CStringUTF32 CStringUTF32::operator+(const CStringUTF32& right) const { - CStringUTF32 result; - result.m_vec.reserve(this->length() + right.length()); - result.m_vec.insert(result.m_vec.end(), m_vec.begin(), m_vec.end()); - result.m_vec.insert(result.m_vec.end(), right.m_vec.begin(), right.m_vec.end()); - return result; + CStringUTF32 result; + result.m_vec.reserve(this->length() + right.length()); + result.m_vec.insert(result.m_vec.end(), m_vec.begin(), m_vec.end()); + result.m_vec.insert(result.m_vec.end(), right.m_vec.begin(), right.m_vec.end()); + return result; } -CStringUTF32& CStringUTF32::operator += (const CStringUTF32 &right) +CStringUTF32& CStringUTF32::operator+=(const CStringUTF32& right) { - m_vec.insert(m_vec.end(), right.m_vec.begin(), right.m_vec.end()); - return *this; + m_vec.insert(m_vec.end(), right.m_vec.begin(), right.m_vec.end()); + return *this; } -CStringUTF32& CStringUTF32::operator += (const uint32_t& symbol) +CStringUTF32& CStringUTF32::operator+=(const uint32_t& symbol) { - m_vec.push_back(symbol); - return *this; + m_vec.push_back(symbol); + return *this; } CStringUTF32 CStringUTF32::substr(size_t start, size_t count) const { - CStringUTF32 result; - result.m_vec.reserve(count); - result.m_vec.insert(result.m_vec.end(), m_vec.begin() + start, m_vec.begin() + start + count); - return result; + CStringUTF32 result; + result.m_vec.reserve(count); + result.m_vec.insert(result.m_vec.end(), m_vec.begin() + start, m_vec.begin() + start + count); + return result; +} + +const uint32_t& CStringUTF32::at(size_t index) const +{ + return this->m_vec.at(index); +} +uint32_t& CStringUTF32::at(size_t index) +{ + return this->m_vec.at(index); } diff --git a/DesktopEditor/common/StringUTF32.h b/DesktopEditor/common/StringUTF32.h index 2341fa7397..561de1afce 100644 --- a/DesktopEditor/common/StringUTF32.h +++ b/DesktopEditor/common/StringUTF32.h @@ -32,45 +32,49 @@ #ifndef STRINGUTF32_HPP #define STRINGUTF32_HPP +#include #include #include -#include -#include "StringExt.h" +#include "../../Common/kernel_config.h" namespace NSStringUtils { - class KERNEL_DECL CStringUTF32 - { - std::vector m_vec; - public: - CStringUTF32(); - CStringUTF32(const CStringUTF32 &other); - CStringUTF32(const wchar_t *other); - CStringUTF32(const std::wstring &other); - CStringUTF32(const std::vector &other); - CStringUTF32(const uint32_t* data, const size_t& count); - virtual ~CStringUTF32(); + class KERNEL_DECL CStringUTF32 + { + std::vector m_vec; - bool empty() const; - size_t length() const; + public: + CStringUTF32(); + CStringUTF32(const CStringUTF32 &other); + CStringUTF32(const wchar_t *other); + CStringUTF32(const std::wstring &other); + CStringUTF32(const std::vector &other); + CStringUTF32(const uint32_t *data, const size_t &count); + virtual ~CStringUTF32(); - std::wstring ToStdWString() const; + bool empty() const; + size_t length() const; - bool operator == (const CStringUTF32 &right) const; - bool operator != (const CStringUTF32 &right) const; - uint32_t &operator [] (size_t index); + std::wstring ToStdWString() const; - CStringUTF32 &operator = (const CStringUTF32 &right); - CStringUTF32 &operator = (const wchar_t *right); - CStringUTF32 &operator = (const std::wstring &right); - CStringUTF32 &operator = (const std::vector &right); + bool operator==(const CStringUTF32 &right) const; + bool operator!=(const CStringUTF32 &right) const; + uint32_t &operator[](size_t index); - CStringUTF32 operator + (const CStringUTF32 &right) const; - CStringUTF32 &operator += (const CStringUTF32 &right); - CStringUTF32 &operator += (const uint32_t& symbol); + CStringUTF32 &operator=(const CStringUTF32 &right); + CStringUTF32 &operator=(const wchar_t *right); + CStringUTF32 &operator=(const std::wstring &right); + CStringUTF32 &operator=(const std::vector &right); - CStringUTF32 substr(size_t start, size_t count) const; - }; -} + CStringUTF32 operator+(const CStringUTF32 &right) const; + CStringUTF32 &operator+=(const CStringUTF32 &right); + CStringUTF32 &operator+=(const uint32_t &symbol); + + CStringUTF32 substr(size_t start, size_t count) const; + + const uint32_t &at(size_t index) const; + uint32_t &at(size_t index); + }; +} // namespace NSStringUtils #endif // STRINGUTF32_HPP diff --git a/DesktopEditor/doctrenderer/app_builder/main.cpp b/DesktopEditor/doctrenderer/app_builder/main.cpp index 76db8e75be..0507c86a16 100644 --- a/DesktopEditor/doctrenderer/app_builder/main.cpp +++ b/DesktopEditor/doctrenderer/app_builder/main.cpp @@ -147,6 +147,7 @@ int main(int argc, char *argv[]) std::wstring sBuildFile = UTF8_TO_U(sBuildFileA); #endif + bool bResult = true; if (true) { NSDoctRenderer::CDocBuilder oBuilder; @@ -159,9 +160,9 @@ int main(int argc, char *argv[]) parse_args(&oBuilder, argc - 1, argv); - oBuilder.Run(sBuildFile.c_str()); + bResult = oBuilder.Run(sBuildFile.c_str()); } NSDoctRenderer::CDocBuilder::Dispose(); - return 0; + return bResult ? 0 : 1; } diff --git a/DesktopEditor/doctrenderer/docbuilder.java/.gitignore b/DesktopEditor/doctrenderer/docbuilder.java/.gitignore new file mode 100644 index 0000000000..f51d072bd6 --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/.gitignore @@ -0,0 +1,3 @@ +result.docx +*.class +*.jar diff --git a/DesktopEditor/doctrenderer/docbuilder.java/make.py b/DesktopEditor/doctrenderer/docbuilder.java/make.py new file mode 100644 index 0000000000..06f07170f1 --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/make.py @@ -0,0 +1,50 @@ +import os +import argparse +import re +import platform + +# NOTE: In JDK 8 and earlier, `javac` does not create the directories specified in the -d option if they do not already exist +# So we need to create them manually +def makedirs(dir): + if not os.path.exists(dir): + os.makedirs(dir) + return + +# return all files with extension `ext` in directory `dir` as string +def getFilesInDir(dir, ext): + files = ''; + for file in os.listdir(dir): + if file.endswith(ext): + # for non-windows systems '$'-symbol in file names should be escaped + if platform.system().lower() != 'windows': + file = re.sub(r'\$', r'\\$', file) + files += ' ' + dir + '/' + file + + return files + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Build Java wrapper for docbuilder library') + parser.add_argument('-H', '--headers', action='store_true', help='Generate C++ JNI header files') + parser.add_argument('-n', '--no-jar', dest='no_jar', action='store_true', help='Build only classes without JAR archive') + args = parser.parse_args() + + file_dir = os.path.dirname(os.path.realpath(__file__)); + os.chdir(file_dir + '/src/java') + + java_files = getFilesInDir('docbuilder', '.java') + java_files += getFilesInDir('docbuilder/utils', '.java') + + # BUILD + classes_dir = file_dir + '/build/classes' + makedirs(classes_dir + '/docbuilder/utils') + headers_dir = file_dir + '/src/jni' + # build all Java classes + os.system('javac -d ' + classes_dir + (' -h ' + headers_dir if args.headers else '') + java_files) + + # PACKING TO JAR + if not args.no_jar: + os.chdir(classes_dir) + class_files = getFilesInDir('docbuilder', '.class') + class_files += getFilesInDir('docbuilder/utils', '.class') + makedirs('../libs') + os.system('jar -cvf ../libs/docbuilder.jar ' + class_files) diff --git a/DesktopEditor/doctrenderer/docbuilder.java/src/java/docbuilder/CDocBuilder.java b/DesktopEditor/doctrenderer/docbuilder.java/src/java/docbuilder/CDocBuilder.java new file mode 100644 index 0000000000..1f252d4198 --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/src/java/docbuilder/CDocBuilder.java @@ -0,0 +1,142 @@ +package docbuilder; + +import docbuilder.utils.NativeLibraryLoader; + +public class CDocBuilder { + public CDocBuilder() { + c_internal = c_Create(); + } + + protected void finalize() { + c_Destroy(c_internal); + } + + public int openFile(String path, String params) { + return c_OpenFile(c_internal, path, params); + } + + public boolean createFile(int type) { + return c_CreateFileByType(c_internal, type); + } + + public boolean createFile(String extension) { + return c_CreateFileByExtension(c_internal, extension); + } + + public void setTmpFolder(String folder) { + c_SetTmpFolder(c_internal, folder); + } + + public int saveFile(int type, String path) { + return c_SaveFileByType(c_internal, type, path); + } + + public int saveFile(int type, String path, String params) { + return c_SaveFileByTypeWithParams(c_internal, type, path, params); + } + + public int saveFile(String extension, String path) { + return c_SaveFileByExtension(c_internal, extension, path); + } + + public int saveFile(String extension, String path, String params) { + return c_SaveFileByExtensionWithParams(c_internal, extension, path, params); + } + + public void closeFile() { + c_CloseFile(c_internal); + } + + public boolean executeCommand(String command) { + return c_ExecuteCommand(c_internal, command); + } + + public boolean executeCommand(String command, CDocBuilderValue retValue) { + return c_ExecuteCommandWithRetValue(c_internal, command, retValue.c_internal); + } + + public boolean run(String path) { + return c_Run(c_internal, path); + } + + public boolean runText(String commands) { + return c_RunText(c_internal, commands); + } + + public void setProperty(String param, String value) { + c_SetProperty(c_internal, param, value); + } + + public void writeData(String path, String value, boolean append) { + c_WriteData(c_internal, path, value, append); + } + + public boolean isSaveWithDoctrendererMode() { + return c_IsSaveWithDoctrendererMode(c_internal); + } + + public String getVersion() { + return c_GetVersion(c_internal); + } + + public CDocBuilderContext getContext() { + return new CDocBuilderContext(c_GetContext(c_internal)); + } + + public static void initialize() { + c_Initialize(); + } + + public static void initialize(String directory) { + if (directory.isEmpty()) + directory = NativeLibraryLoader.getLibPath().toString(); + c_InitializeWithDirectory(directory); + } + + public static void dispose() { + c_Dispose(); + } + + // Native code + static { + docbuilder.utils.NativeLibraryLoader.loadLibraries(); + } + + long c_internal = 0; + + private static native long c_Create(); + private static native void c_Destroy(long self); + + private static native int c_OpenFile(long self, String path, String params); + private static native boolean c_CreateFileByType(long self, int type); + private static native boolean c_CreateFileByExtension(long self, String extension); + + private static native void c_SetTmpFolder(long self, String folder); + + private static native int c_SaveFileByType(long self, int type, String path); + private static native int c_SaveFileByTypeWithParams(long self, int type, String path, String params); + private static native int c_SaveFileByExtension(long self, String extension, String path); + private static native int c_SaveFileByExtensionWithParams(long self, String extension, String path, String params); + + private static native void c_CloseFile(long self); + + private static native boolean c_ExecuteCommand(long self, String command); + private static native boolean c_ExecuteCommandWithRetValue(long self, String command, long retValue); + + private static native boolean c_Run(long self, String path); + private static native boolean c_RunText(long self, String commands); + + private static native void c_SetProperty(long self, String param, String value); + + private static native void c_WriteData(long self, String path, String value, boolean append); + + private static native boolean c_IsSaveWithDoctrendererMode(long self); + + private static native String c_GetVersion(long self); + + private static native long c_GetContext(long self); + + private static native void c_Initialize(); + private static native void c_InitializeWithDirectory(String directory); + private static native void c_Dispose(); +} diff --git a/DesktopEditor/doctrenderer/docbuilder.java/src/java/docbuilder/CDocBuilderContext.java b/DesktopEditor/doctrenderer/docbuilder.java/src/java/docbuilder/CDocBuilderContext.java new file mode 100644 index 0000000000..68b199f3ee --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/src/java/docbuilder/CDocBuilderContext.java @@ -0,0 +1,69 @@ +package docbuilder; + +public class CDocBuilderContext { + public CDocBuilderContext() { + c_internal = c_Create(); + } + + CDocBuilderContext(long internal) { + c_internal = internal; + } + + public CDocBuilderContext(CDocBuilderContext other) { + c_internal = c_Copy(other.c_internal); + } + + protected void finalize() { + c_Destroy(c_internal); + } + + public CDocBuilderValue createUndefined() { + return new CDocBuilderValue(c_CreateUndefined(c_internal)); + } + + public CDocBuilderValue createNull() { + return new CDocBuilderValue(c_CreateNull(c_internal)); + } + + public CDocBuilderValue createObject() { + return new CDocBuilderValue(c_CreateObject(c_internal)); + } + + public CDocBuilderValue createArray(int length) { + return new CDocBuilderValue(c_CreateArray(c_internal, length)); + } + + public CDocBuilderValue getGlobal() { + return new CDocBuilderValue(c_GetGlobal(c_internal)); + } + + public CDocBuilderContextScope createScope() { + return new CDocBuilderContextScope(c_CreateScope(c_internal)); + } + + public boolean isError() { + return c_IsError(c_internal); + } + + // Native code + static { + docbuilder.utils.NativeLibraryLoader.loadLibraries(); + } + + long c_internal = 0; + + private static native long c_Create(); + private static native long c_Copy(long other); + private static native void c_Destroy(long self); + + private static native long c_CreateUndefined(long self); + private static native long c_CreateNull(long self); + private static native long c_CreateObject(long self); + private static native long c_CreateArray(long self, int length); + + private static native long c_GetGlobal(long self); + + private static native long c_CreateScope(long self); + + private static native boolean c_IsError(long self); +} diff --git a/DesktopEditor/doctrenderer/docbuilder.java/src/java/docbuilder/CDocBuilderContextScope.java b/DesktopEditor/doctrenderer/docbuilder.java/src/java/docbuilder/CDocBuilderContextScope.java new file mode 100644 index 0000000000..e50742f35f --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/src/java/docbuilder/CDocBuilderContextScope.java @@ -0,0 +1,36 @@ +package docbuilder; + +public class CDocBuilderContextScope { + public CDocBuilderContextScope() { + c_internal = c_Create(); + } + + CDocBuilderContextScope(long internal) { + c_internal = internal; + } + + public CDocBuilderContextScope(CDocBuilderContextScope other) { + c_internal = c_Copy(other.c_internal); + } + + protected void finalize() { + c_Destroy(c_internal); + } + + public void close() { + c_Close(c_internal); + } + + // Native code + static { + docbuilder.utils.NativeLibraryLoader.loadLibraries(); + } + + long c_internal = 0; + + private static native long c_Create(); + private static native long c_Copy(long other); + private static native void c_Destroy(long self); + + private static native void c_Close(long self); +} diff --git a/DesktopEditor/doctrenderer/docbuilder.java/src/java/docbuilder/CDocBuilderValue.java b/DesktopEditor/doctrenderer/docbuilder.java/src/java/docbuilder/CDocBuilderValue.java new file mode 100644 index 0000000000..ba17a2ef53 --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/src/java/docbuilder/CDocBuilderValue.java @@ -0,0 +1,278 @@ +package docbuilder; + +public class CDocBuilderValue { + public CDocBuilderValue() { + c_internal = c_Create(); + } + + CDocBuilderValue(long internal) { + c_internal = internal; + } + + public CDocBuilderValue(CDocBuilderValue other) { + c_internal = c_Copy(other.c_internal); + } + + protected void finalize() + { + c_Destroy(c_internal); + } + + public boolean isEmpty() + { + return c_IsEmpty(c_internal); + } + + public void clear() + { + c_Clear(c_internal); + } + + public boolean isNull() + { + return c_IsNull(c_internal); + } + + public boolean isUndefined() + { + return c_IsUndefined(c_internal); + } + + public boolean isInt() + { + return c_IsInt(c_internal); + } + + public boolean isDouble() + { + return c_IsDouble(c_internal); + } + + public boolean isString() + { + return c_IsString(c_internal); + } + + public boolean isFunction() + { + return c_IsFunction(c_internal); + } + + public boolean isObject() + { + return c_IsObject(c_internal); + } + + public boolean isArray() + { + return c_IsArray(c_internal); + } + + public int getLength() + { + return c_GetLength(c_internal); + } + + public boolean toBool() + { + return c_ToBool(c_internal); + } + + public int toInt() + { + return c_ToInt(c_internal); + } + + public double toDouble() + { + return c_ToDouble(c_internal); + } + + public String toString() + { + return c_ToString(c_internal); + } + + public CDocBuilderValue getProperty(String name) { + return new CDocBuilderValue(c_GetProperty(c_internal, name)); + } + + public CDocBuilderValue get(String name) { + return new CDocBuilderValue(c_GetProperty(c_internal, name)); + } + + public CDocBuilderValue get(int index) { + return new CDocBuilderValue(c_GetByIndex(c_internal, index)); + } + + public void setProperty(String name, Object value) { + CDocBuilderValue docBuilderValue = getValueFromObject(value); + c_SetProperty(c_internal, name, docBuilderValue.c_internal); + } + + public void set(String name, Object value) { + CDocBuilderValue docBuilderValue = getValueFromObject(value); + c_SetProperty(c_internal, name, docBuilderValue.c_internal); + } + + public void set(int index, Object value) { + CDocBuilderValue docBuilderValue = getValueFromObject(value); + c_SetByIndex(c_internal, index, docBuilderValue.c_internal); + } + + public CDocBuilderValue(boolean value) { + c_internal = c_CreateWithBool(value); + } + + public CDocBuilderValue(int value) { + c_internal = c_CreateWithInt(value); + } + + public CDocBuilderValue(double value) { + c_internal = c_CreateWithDouble(value); + } + + public CDocBuilderValue(String value) { + c_internal = c_CreateWithString(value); + } + + public CDocBuilderValue(Object[] values) { + int length = values.length; + c_internal = c_CreateArray(length); + for (int i = 0; i < length; i++) { + this.set(i, getValueFromObject(values[i])); + } + } + + static CDocBuilderValue getValueFromObject(Object obj) { + if (obj instanceof CDocBuilderValue) { + return (CDocBuilderValue)obj; + } else if (obj instanceof Boolean) { + return new CDocBuilderValue((Boolean)obj); + } else if (obj instanceof Integer) { + return new CDocBuilderValue((Integer)obj); + } else if (obj instanceof Double) { + return new CDocBuilderValue((Double)obj); + } else if (obj instanceof String) { + return new CDocBuilderValue((String)obj); + } else if (obj instanceof Object[]) { + return new CDocBuilderValue((Object[])obj); + } else { + throw new IllegalArgumentException("Unsupported type for CDocBuilderValue"); + } + } + + public static CDocBuilderValue createUndefined() { + return new CDocBuilderValue(c_CreateUndefined()); + } + + public static CDocBuilderValue createNull() { + return new CDocBuilderValue(c_CreateNull()); + } + + public static CDocBuilderValue createArray(int length) { + return new CDocBuilderValue(c_CreateArray(length)); + } + + public CDocBuilderValue call(String name) { + return new CDocBuilderValue(c_Call0(c_internal, name)); + } + + public CDocBuilderValue call(String name, Object p1) { + CDocBuilderValue pValue1 = getValueFromObject(p1); + return new CDocBuilderValue(c_Call1(c_internal, name, pValue1.c_internal)); + } + + public CDocBuilderValue call(String name, Object p1, Object p2) { + CDocBuilderValue pValue1 = getValueFromObject(p1); + CDocBuilderValue pValue2 = getValueFromObject(p2); + return new CDocBuilderValue(c_Call2(c_internal, name, pValue1.c_internal, pValue2.c_internal)); + } + + public CDocBuilderValue call(String name, Object p1, Object p2, Object p3) { + CDocBuilderValue pValue1 = getValueFromObject(p1); + CDocBuilderValue pValue2 = getValueFromObject(p2); + CDocBuilderValue pValue3 = getValueFromObject(p3); + return new CDocBuilderValue(c_Call3(c_internal, name, pValue1.c_internal, pValue2.c_internal, pValue3.c_internal)); + } + + public CDocBuilderValue call(String name, Object p1, Object p2, Object p3, Object p4) { + CDocBuilderValue pValue1 = getValueFromObject(p1); + CDocBuilderValue pValue2 = getValueFromObject(p2); + CDocBuilderValue pValue3 = getValueFromObject(p3); + CDocBuilderValue pValue4 = getValueFromObject(p4); + return new CDocBuilderValue(c_Call4(c_internal, name, pValue1.c_internal, pValue2.c_internal, pValue3.c_internal, pValue4.c_internal)); + } + + public CDocBuilderValue call(String name, Object p1, Object p2, Object p3, Object p4, Object p5) { + CDocBuilderValue pValue1 = getValueFromObject(p1); + CDocBuilderValue pValue2 = getValueFromObject(p2); + CDocBuilderValue pValue3 = getValueFromObject(p3); + CDocBuilderValue pValue4 = getValueFromObject(p4); + CDocBuilderValue pValue5 = getValueFromObject(p5); + return new CDocBuilderValue(c_Call5(c_internal, name, pValue1.c_internal, pValue2.c_internal, pValue3.c_internal, pValue4.c_internal, pValue5.c_internal)); + } + + public CDocBuilderValue call(String name, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) { + CDocBuilderValue pValue1 = getValueFromObject(p1); + CDocBuilderValue pValue2 = getValueFromObject(p2); + CDocBuilderValue pValue3 = getValueFromObject(p3); + CDocBuilderValue pValue4 = getValueFromObject(p4); + CDocBuilderValue pValue5 = getValueFromObject(p5); + CDocBuilderValue pValue6 = getValueFromObject(p6); + return new CDocBuilderValue(c_Call6(c_internal, name, pValue1.c_internal, pValue2.c_internal, pValue3.c_internal, pValue4.c_internal, pValue5.c_internal, pValue6.c_internal)); + } + + // Native code + static { + docbuilder.utils.NativeLibraryLoader.loadLibraries(); + } + + long c_internal = 0; + + private static native long c_Create(); + private static native long c_Copy(long other); + private static native void c_Destroy(long self); + + private static native boolean c_IsEmpty(long self); + private static native void c_Clear(long self); + + private static native boolean c_IsNull(long self); + private static native boolean c_IsUndefined(long self); + private static native boolean c_IsInt(long self); + private static native boolean c_IsDouble(long self); + private static native boolean c_IsString(long self); + private static native boolean c_IsFunction(long self); + private static native boolean c_IsObject(long self); + private static native boolean c_IsArray(long self); + + private static native int c_GetLength(long self); + + private static native boolean c_ToBool(long self); + private static native int c_ToInt(long self); + private static native double c_ToDouble(long self); + private static native String c_ToString(long self); + + private static native long c_GetProperty(long self, String name); + private static native long c_GetByIndex(long self, int index); + + private static native void c_SetProperty(long self, String name, long value); + private static native void c_SetByIndex(long self, int index, long value); + + private static native long c_CreateWithBool(boolean value); + private static native long c_CreateWithInt(int value); + private static native long c_CreateWithDouble(double value); + private static native long c_CreateWithString(String value); + + private static native long c_CreateUndefined(); + private static native long c_CreateNull(); + private static native long c_CreateArray(int length); + + private static native long c_Call0(long self, String name); + private static native long c_Call1(long self, String name, long p1); + private static native long c_Call2(long self, String name, long p1, long p2); + private static native long c_Call3(long self, String name, long p1, long p2, long p3); + private static native long c_Call4(long self, String name, long p1, long p2, long p3, long p4); + private static native long c_Call5(long self, String name, long p1, long p2, long p3, long p4, long p5); + private static native long c_Call6(long self, String name, long p1, long p2, long p3, long p4, long p5, long p6); +} diff --git a/DesktopEditor/doctrenderer/docbuilder.java/src/java/docbuilder/FileTypes.java b/DesktopEditor/doctrenderer/docbuilder.java/src/java/docbuilder/FileTypes.java new file mode 100644 index 0000000000..138248181b --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/src/java/docbuilder/FileTypes.java @@ -0,0 +1,47 @@ +package docbuilder; + +public class FileTypes { + public class Document { + private static final int MASK = 0x0040; + public static final int DOCX = MASK + 0x0001; + public static final int DOC = MASK + 0x0002; + public static final int ODT = MASK + 0x0003; + public static final int RTF = MASK + 0x0004; + public static final int TXT = MASK + 0x0005; + public static final int DOTX = MASK + 0x000c; + public static final int OTT = MASK + 0x000f; + public static final int HTML = MASK + 0x0012; + public static final int OFORM_PDF = MASK + 0x0017; + } + + public class Presentation { + private static final int MASK = 0x0080; + public static final int PPTX = MASK + 0x0001; + public static final int PPT = MASK + 0x0002; + public static final int ODP = MASK + 0x0003; + public static final int PPSX = MASK + 0x0004; + public static final int POTX = MASK + 0x0007; + public static final int OTP = MASK + 0x000a; + } + + public class Spreadsheet { + private static final int MASK = 0x0100; + public static final int XLSX = MASK + 0x0001; + public static final int XLS = MASK + 0x0002; + public static final int ODS = MASK + 0x0003; + public static final int CSV = MASK + 0x0004; + public static final int XLTX = MASK + 0x0006; + public static final int OTS = MASK + 0x0009; + } + + public class Graphics { + private static final int PDF_MASK = 0x0200; + public static final int PDF = PDF_MASK + 0x0001; + public static final int PDFA = PDF_MASK + 0x0009; + + private static final int IMAGE_MASK = 0x0400; + public static final int JPG = IMAGE_MASK + 0x0001; + public static final int PNG = IMAGE_MASK + 0x0005; + public static final int BMP = IMAGE_MASK + 0x0008; + } +} diff --git a/DesktopEditor/doctrenderer/docbuilder.java/src/java/docbuilder/utils/NativeLibraryLoader.java b/DesktopEditor/doctrenderer/docbuilder.java/src/java/docbuilder/utils/NativeLibraryLoader.java new file mode 100644 index 0000000000..3ea326d46e --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/src/java/docbuilder/utils/NativeLibraryLoader.java @@ -0,0 +1,86 @@ +package docbuilder.utils; + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; + +public class NativeLibraryLoader { + // helper class for retrieving information about current OS + public static class OSChecker { + private static String osName = System.getProperty("os.name").toLowerCase(); + + public static boolean isWindows() { + return (osName.indexOf("win") >= 0); + } + + public static boolean isMac() { + return (osName.indexOf("mac") >= 0); + } + + public static boolean isLinux() { + return (osName.indexOf("nix") >= 0 || osName.indexOf("nux") >= 0 || osName.indexOf("aix") > 0); + } + } + + static { + try { + Path libDirPath = getLibPath(); + // load icu libraries + if (OSChecker.isWindows()) { + System.load(libDirPath.resolve("icudt58.dll").toString()); + System.load(libDirPath.resolve("icuuc58.dll").toString()); + } else if (OSChecker.isMac()) { + System.load(libDirPath.resolve("libicudata.58.dylib").toString()); + System.load(libDirPath.resolve("libicuuc.58.dylib").toString()); + } else if (OSChecker.isLinux()) { + System.load(libDirPath.resolve("libicudata.so.58").toString()); + System.load(libDirPath.resolve("libicuuc.so.58").toString()); + } else { + throw new RuntimeException("Unsupported OS"); + } + + String[] libs = {"UnicodeConverter", "kernel", "kernel_network", "graphics", "doctrenderer", "docbuilder.jni"}; + + String prefix = ""; + if (OSChecker.isMac() || OSChecker.isLinux()) { + prefix = "lib"; + } + + String extension = ""; + if (OSChecker.isWindows()) { + extension = ".dll"; + } else if (OSChecker.isMac()) { + extension = ".dylib"; + } else { + extension = ".so"; + } + + for (String lib : libs) { + System.load(libDirPath.resolve(prefix + lib + extension).toString()); + } + } catch (UnsatisfiedLinkError e) { + throw new RuntimeException("Cannot load dynamic libraries. Check if JAR file is in the same directory as all docbuilder libraries."); + } + } + + // Returns path to the directory containing current JAR + public static Path getLibPath() + { + URL url = NativeLibraryLoader.class.getProtectionDomain().getCodeSource().getLocation(); + try { + File jarFile = new File(url.toURI()); + Path jarPath = jarFile.toPath(); + Path libDirPath = jarPath.getParent(); + + return libDirPath; + } catch (URISyntaxException exception) { + // Very unlikely to be happened + throw new RuntimeException("Cannot convert URI of the NativeLibraryLoader.class to URL"); + } + } + + public static void loadLibraries() { + // No-op, just to force the class loading + } +} diff --git a/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilder.cpp b/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilder.cpp new file mode 100644 index 0000000000..4873c76436 --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilder.cpp @@ -0,0 +1,179 @@ +#include "docbuilder_CDocBuilder.h" + +#include + +#include "docbuilder.h" +// for wchar_t <=> char conversion +#include "../../../../common/File.h" + +using namespace NSDoctRenderer; + +static std::wstring wstringFromJavaString(JNIEnv* env, jstring jstr) +{ + const char* strUtf = env->GetStringUTFChars(jstr, nullptr); + std::wstring wstr = NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)strUtf, (LONG)strlen(strUtf)); + env->ReleaseStringUTFChars(jstr, strUtf); + return wstr; +} + +jlong Java_docbuilder_CDocBuilder_c_1Create(JNIEnv* env, jclass cls) +{ + return reinterpret_cast(new CDocBuilder()); +} + +void Java_docbuilder_CDocBuilder_c_1Destroy(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + delete pSelf; +} + +jint Java_docbuilder_CDocBuilder_c_1OpenFile(JNIEnv* env, jclass cls, jlong self, jstring path, jstring params) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + std::wstring strPath = wstringFromJavaString(env, path); + std::wstring strParams = wstringFromJavaString(env, params); + return (jint)pSelf->OpenFile(strPath.c_str(), strParams.c_str()); +} + +jboolean Java_docbuilder_CDocBuilder_c_1CreateFileByType(JNIEnv* env, jclass cls, jlong self, jint type) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + return (jboolean)pSelf->CreateFile((int)type); +} + +jboolean Java_docbuilder_CDocBuilder_c_1CreateFileByExtension(JNIEnv* env, jclass cls, jlong self, jstring extension) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + std::wstring strExtension = wstringFromJavaString(env, extension); + return (jboolean)pSelf->CreateFile(strExtension.c_str()); +} + +void Java_docbuilder_CDocBuilder_c_1SetTmpFolder(JNIEnv* env, jclass cls, jlong self, jstring folder) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + std::wstring strFolder = wstringFromJavaString(env, folder); + pSelf->SetTmpFolder(strFolder.c_str()); +} + +jint Java_docbuilder_CDocBuilder_c_1SaveFileByType(JNIEnv* env, jclass cls, jlong self, jint type, jstring path) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + std::wstring strPath = wstringFromJavaString(env, path); + return (jint)pSelf->SaveFile((int)type, strPath.c_str()); +} + +jint Java_docbuilder_CDocBuilder_c_1SaveFileByTypeWithParams(JNIEnv* env, jclass cls, jlong self, jint type, jstring path, jstring params) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + std::wstring strPath = wstringFromJavaString(env, path); + std::wstring strParams = wstringFromJavaString(env, params); + return (jint)pSelf->SaveFile((int)type, strPath.c_str(), strParams.c_str()); +} + +jint Java_docbuilder_CDocBuilder_c_1SaveFileByExtension(JNIEnv* env, jclass cls, jlong self, jstring extension, jstring path) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + std::wstring strExtension = wstringFromJavaString(env, extension); + std::wstring strPath = wstringFromJavaString(env, path); + return (jint)pSelf->SaveFile(strExtension.c_str(), strPath.c_str()); +} + +jint Java_docbuilder_CDocBuilder_c_1SaveFileByExtensionWithParams(JNIEnv* env, jclass cls, jlong self, jstring extension, jstring path, jstring params) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + std::wstring strExtension = wstringFromJavaString(env, extension); + std::wstring strPath = wstringFromJavaString(env, path); + std::wstring strParams = wstringFromJavaString(env, params); + return (jint)pSelf->SaveFile(strExtension.c_str(), strPath.c_str(), strParams.c_str()); +} + +void Java_docbuilder_CDocBuilder_c_1CloseFile(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + pSelf->CloseFile(); +} + +jboolean Java_docbuilder_CDocBuilder_c_1ExecuteCommand(JNIEnv* env, jclass cls, jlong self, jstring command) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + std::wstring strCommand = wstringFromJavaString(env, command); + return (jboolean)pSelf->ExecuteCommand(strCommand.c_str()); +} + +jboolean Java_docbuilder_CDocBuilder_c_1ExecuteCommandWithRetValue(JNIEnv* env, jclass cls, jlong self, jstring command, jlong retValue) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + std::wstring strCommand = wstringFromJavaString(env, command); + CDocBuilderValue* pRetValue = reinterpret_cast(retValue); + return (jboolean)pSelf->ExecuteCommand(strCommand.c_str(), pRetValue); +} + +jboolean Java_docbuilder_CDocBuilder_c_1Run(JNIEnv* env, jclass cls, jlong self, jstring path) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + std::wstring strPath = wstringFromJavaString(env, path); + return (jboolean)pSelf->Run(strPath.c_str()); +} + +jboolean Java_docbuilder_CDocBuilder_c_1RunText(JNIEnv* env, jclass cls, jlong self, jstring commands) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + const char* strUtfCommands = env->GetStringUTFChars(commands, nullptr); + jboolean result = (jboolean)pSelf->RunTextA(strUtfCommands); + env->ReleaseStringUTFChars(commands, strUtfCommands); + return result; +} + +void Java_docbuilder_CDocBuilder_c_1SetProperty(JNIEnv* env, jclass cls, jlong self, jstring param, jstring value) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + const char* strUtfParam = env->GetStringUTFChars(param, nullptr); + std::wstring strValue = wstringFromJavaString(env, value); + pSelf->SetProperty(strUtfParam, strValue.c_str()); + env->ReleaseStringUTFChars(param, strUtfParam); +} + +void Java_docbuilder_CDocBuilder_c_1WriteData(JNIEnv* env, jclass cls, jlong self, jstring path, jstring data, jboolean append) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + std::wstring strPath = wstringFromJavaString(env, path); + std::wstring strData = wstringFromJavaString(env, data); + pSelf->WriteData(strPath.c_str(), strData.c_str(), (bool)append); +} + +jboolean Java_docbuilder_CDocBuilder_c_1IsSaveWithDoctrendererMode(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + return (jboolean)pSelf->IsSaveWithDoctrendererMode(); +} + +jstring Java_docbuilder_CDocBuilder_c_1GetVersion(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + char* strUtfVersion = pSelf->GetVersion(); + jstring jstrVersion = env->NewStringUTF(strUtfVersion); + delete[] strUtfVersion; + return jstrVersion; +} + +jlong Java_docbuilder_CDocBuilder_c_1GetContext(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilder* pSelf = reinterpret_cast(self); + return reinterpret_cast(new CDocBuilderContext(pSelf->GetContext())); +} + +void Java_docbuilder_CDocBuilder_c_1Initialize(JNIEnv* env, jclass cls) +{ + CDocBuilder::Initialize(); +} + +void Java_docbuilder_CDocBuilder_c_1InitializeWithDirectory(JNIEnv* env, jclass cls, jstring directory) +{ + std::wstring strDirectory = wstringFromJavaString(env, directory); + CDocBuilder::Initialize(strDirectory.c_str()); +} + +void Java_docbuilder_CDocBuilder_c_1Dispose(JNIEnv* env, jclass cls) +{ + CDocBuilder::Dispose(); +} diff --git a/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilder.h b/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilder.h new file mode 100644 index 0000000000..f7fce7a1eb --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilder.h @@ -0,0 +1,197 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class docbuilder_CDocBuilder */ + +#ifndef _Included_docbuilder_CDocBuilder +#define _Included_docbuilder_CDocBuilder +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: docbuilder_CDocBuilder + * Method: c_Create + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilder_c_1Create + (JNIEnv *, jclass); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_Destroy + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_docbuilder_CDocBuilder_c_1Destroy + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_OpenFile + * Signature: (JLjava/lang/String;Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_docbuilder_CDocBuilder_c_1OpenFile + (JNIEnv *, jclass, jlong, jstring, jstring); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_CreateFileByType + * Signature: (JI)Z + */ +JNIEXPORT jboolean JNICALL Java_docbuilder_CDocBuilder_c_1CreateFileByType + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_CreateFileByExtension + * Signature: (JLjava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL Java_docbuilder_CDocBuilder_c_1CreateFileByExtension + (JNIEnv *, jclass, jlong, jstring); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_SetTmpFolder + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_docbuilder_CDocBuilder_c_1SetTmpFolder + (JNIEnv *, jclass, jlong, jstring); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_SaveFileByType + * Signature: (JILjava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_docbuilder_CDocBuilder_c_1SaveFileByType + (JNIEnv *, jclass, jlong, jint, jstring); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_SaveFileByTypeWithParams + * Signature: (JILjava/lang/String;Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_docbuilder_CDocBuilder_c_1SaveFileByTypeWithParams + (JNIEnv *, jclass, jlong, jint, jstring, jstring); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_SaveFileByExtension + * Signature: (JLjava/lang/String;Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_docbuilder_CDocBuilder_c_1SaveFileByExtension + (JNIEnv *, jclass, jlong, jstring, jstring); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_SaveFileByExtensionWithParams + * Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_docbuilder_CDocBuilder_c_1SaveFileByExtensionWithParams + (JNIEnv *, jclass, jlong, jstring, jstring, jstring); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_CloseFile + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_docbuilder_CDocBuilder_c_1CloseFile + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_ExecuteCommand + * Signature: (JLjava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL Java_docbuilder_CDocBuilder_c_1ExecuteCommand + (JNIEnv *, jclass, jlong, jstring); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_ExecuteCommandWithRetValue + * Signature: (JLjava/lang/String;J)Z + */ +JNIEXPORT jboolean JNICALL Java_docbuilder_CDocBuilder_c_1ExecuteCommandWithRetValue + (JNIEnv *, jclass, jlong, jstring, jlong); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_Run + * Signature: (JLjava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL Java_docbuilder_CDocBuilder_c_1Run + (JNIEnv *, jclass, jlong, jstring); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_RunText + * Signature: (JLjava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL Java_docbuilder_CDocBuilder_c_1RunText + (JNIEnv *, jclass, jlong, jstring); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_SetProperty + * Signature: (JLjava/lang/String;Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_docbuilder_CDocBuilder_c_1SetProperty + (JNIEnv *, jclass, jlong, jstring, jstring); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_WriteData + * Signature: (JLjava/lang/String;Ljava/lang/String;Z)V + */ +JNIEXPORT void JNICALL Java_docbuilder_CDocBuilder_c_1WriteData + (JNIEnv *, jclass, jlong, jstring, jstring, jboolean); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_IsSaveWithDoctrendererMode + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_docbuilder_CDocBuilder_c_1IsSaveWithDoctrendererMode + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_GetVersion + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_docbuilder_CDocBuilder_c_1GetVersion + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_GetContext + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilder_c_1GetContext + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_Initialize + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_docbuilder_CDocBuilder_c_1Initialize + (JNIEnv *, jclass); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_InitializeWithDirectory + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_docbuilder_CDocBuilder_c_1InitializeWithDirectory + (JNIEnv *, jclass, jstring); + +/* + * Class: docbuilder_CDocBuilder + * Method: c_Dispose + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_docbuilder_CDocBuilder_c_1Dispose + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilderContext.cpp b/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilderContext.cpp new file mode 100644 index 0000000000..8398d14c37 --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilderContext.cpp @@ -0,0 +1,64 @@ +#include "docbuilder_CDocBuilderContext.h" + +#include "docbuilder.h" + +using namespace NSDoctRenderer; + +jlong Java_docbuilder_CDocBuilderContext_c_1Create(JNIEnv* env, jclass cls) +{ + return reinterpret_cast(new CDocBuilderContext()); +} + +jlong Java_docbuilder_CDocBuilderContext_c_1Copy(JNIEnv* env, jclass cls, jlong other) +{ + CDocBuilderContext* pOther = reinterpret_cast(other); + return reinterpret_cast(new CDocBuilderContext(*pOther)); +} + +void Java_docbuilder_CDocBuilderContext_c_1Destroy(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderContext* pSelf = reinterpret_cast(self); + delete pSelf; +} + +jlong Java_docbuilder_CDocBuilderContext_c_1CreateUndefined(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderContext* pSelf = reinterpret_cast(self); + return reinterpret_cast(new CDocBuilderValue(pSelf->CreateUndefined())); +} + +jlong Java_docbuilder_CDocBuilderContext_c_1CreateNull(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderContext* pSelf = reinterpret_cast(self); + return reinterpret_cast(new CDocBuilderValue(pSelf->CreateNull())); +} + +jlong Java_docbuilder_CDocBuilderContext_c_1CreateObject(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderContext* pSelf = reinterpret_cast(self); + return reinterpret_cast(new CDocBuilderValue(pSelf->CreateObject())); +} + +jlong Java_docbuilder_CDocBuilderContext_c_1CreateArray(JNIEnv* env, jclass cls, jlong self, jint length) +{ + CDocBuilderContext* pSelf = reinterpret_cast(self); + return reinterpret_cast(new CDocBuilderValue(pSelf->CreateArray((int)length))); +} + +jlong Java_docbuilder_CDocBuilderContext_c_1GetGlobal(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderContext* pSelf = reinterpret_cast(self); + return reinterpret_cast(new CDocBuilderValue(pSelf->GetGlobal())); +} + +jlong Java_docbuilder_CDocBuilderContext_c_1CreateScope(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderContext* pSelf = reinterpret_cast(self); + return reinterpret_cast(new CDocBuilderContextScope(pSelf->CreateScope())); +} + +jboolean Java_docbuilder_CDocBuilderContext_c_1IsError(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderContext* pSelf = reinterpret_cast(self); + return (jboolean)pSelf->IsError(); +} diff --git a/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilderContext.h b/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilderContext.h new file mode 100644 index 0000000000..43e72ee4f1 --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilderContext.h @@ -0,0 +1,93 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class docbuilder_CDocBuilderContext */ + +#ifndef _Included_docbuilder_CDocBuilderContext +#define _Included_docbuilder_CDocBuilderContext +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: docbuilder_CDocBuilderContext + * Method: c_Create + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderContext_c_1Create + (JNIEnv *, jclass); + +/* + * Class: docbuilder_CDocBuilderContext + * Method: c_Copy + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderContext_c_1Copy + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderContext + * Method: c_Destroy + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_docbuilder_CDocBuilderContext_c_1Destroy + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderContext + * Method: c_CreateUndefined + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderContext_c_1CreateUndefined + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderContext + * Method: c_CreateNull + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderContext_c_1CreateNull + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderContext + * Method: c_CreateObject + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderContext_c_1CreateObject + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderContext + * Method: c_CreateArray + * Signature: (JI)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderContext_c_1CreateArray + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: docbuilder_CDocBuilderContext + * Method: c_GetGlobal + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderContext_c_1GetGlobal + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderContext + * Method: c_CreateScope + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderContext_c_1CreateScope + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderContext + * Method: c_IsError + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_docbuilder_CDocBuilderContext_c_1IsError + (JNIEnv *, jclass, jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilderContextScope.cpp b/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilderContextScope.cpp new file mode 100644 index 0000000000..c63c69ae48 --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilderContextScope.cpp @@ -0,0 +1,28 @@ +#include "docbuilder_CDocBuilderContextScope.h" + +#include "docbuilder.h" + +using namespace NSDoctRenderer; + +jlong Java_docbuilder_CDocBuilderContextScope_c_1Create(JNIEnv* env, jclass cls) +{ + return reinterpret_cast(new CDocBuilderContextScope()); +} + +jlong Java_docbuilder_CDocBuilderContextScope_c_1Copy(JNIEnv* env, jclass cls, jlong other) +{ + CDocBuilderContextScope* pOther = reinterpret_cast(other); + return reinterpret_cast(new CDocBuilderContextScope(*pOther)); +} + +void Java_docbuilder_CDocBuilderContextScope_c_1Destroy(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderContextScope* pSelf = reinterpret_cast(self); + delete pSelf; +} + +void Java_docbuilder_CDocBuilderContextScope_c_1Close(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderContextScope* pSelf = reinterpret_cast(self); + pSelf->Close(); +} diff --git a/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilderContextScope.h b/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilderContextScope.h new file mode 100644 index 0000000000..3ead55b861 --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilderContextScope.h @@ -0,0 +1,45 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class docbuilder_CDocBuilderContextScope */ + +#ifndef _Included_docbuilder_CDocBuilderContextScope +#define _Included_docbuilder_CDocBuilderContextScope +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: docbuilder_CDocBuilderContextScope + * Method: c_Create + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderContextScope_c_1Create + (JNIEnv *, jclass); + +/* + * Class: docbuilder_CDocBuilderContextScope + * Method: c_Copy + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderContextScope_c_1Copy + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderContextScope + * Method: c_Destroy + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_docbuilder_CDocBuilderContextScope_c_1Destroy + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderContextScope + * Method: c_Close + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_docbuilder_CDocBuilderContextScope_c_1Close + (JNIEnv *, jclass, jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilderValue.cpp b/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilderValue.cpp new file mode 100644 index 0000000000..cfb3099ea9 --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilderValue.cpp @@ -0,0 +1,273 @@ +#include "docbuilder_CDocBuilderValue.h" + +#include + +#include "docbuilder.h" +// for wchar_t <=> char conversion +#include "../../../../common/File.h" + +using namespace NSDoctRenderer; + +jlong Java_docbuilder_CDocBuilderValue_c_1Create(JNIEnv* env, jclass cls) +{ + return reinterpret_cast(new CDocBuilderValue()); +} + +jlong Java_docbuilder_CDocBuilderValue_c_1Copy(JNIEnv* env, jclass cls, jlong other) +{ + CDocBuilderValue* pOther = reinterpret_cast(other); + return reinterpret_cast(new CDocBuilderValue(*pOther)); +} + +void Java_docbuilder_CDocBuilderValue_c_1Destroy(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + delete pSelf; +} + +jboolean Java_docbuilder_CDocBuilderValue_c_1IsEmpty(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + return (jboolean)pSelf->IsEmpty(); +} + +void Java_docbuilder_CDocBuilderValue_c_1Clear(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + pSelf->Clear(); +} + +jboolean Java_docbuilder_CDocBuilderValue_c_1IsNull(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + return (jboolean)pSelf->IsNull(); +} + +jboolean Java_docbuilder_CDocBuilderValue_c_1IsUndefined(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + return (jboolean)pSelf->IsUndefined(); +} + +jboolean Java_docbuilder_CDocBuilderValue_c_1IsInt(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + return (jboolean)pSelf->IsInt(); +} + +jboolean Java_docbuilder_CDocBuilderValue_c_1IsDouble(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + return (jboolean)pSelf->IsDouble(); +} + +jboolean Java_docbuilder_CDocBuilderValue_c_1IsString(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + return (jboolean)pSelf->IsString(); +} + +jboolean Java_docbuilder_CDocBuilderValue_c_1IsFunction(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + return (jboolean)pSelf->IsFunction(); +} + +jboolean Java_docbuilder_CDocBuilderValue_c_1IsObject(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + return (jboolean)pSelf->IsObject(); +} + +jboolean Java_docbuilder_CDocBuilderValue_c_1IsArray(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + return (jboolean)pSelf->IsArray(); +} + +jint Java_docbuilder_CDocBuilderValue_c_1GetLength(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + return (jint)pSelf->GetLength(); +} + +jboolean Java_docbuilder_CDocBuilderValue_c_1ToBool(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + return (jboolean)pSelf->ToBool(); +} + +jint Java_docbuilder_CDocBuilderValue_c_1ToInt(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + return (jint)pSelf->ToInt(); +} + +jdouble Java_docbuilder_CDocBuilderValue_c_1ToDouble(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + return (jdouble)pSelf->ToDouble(); +} + +jstring Java_docbuilder_CDocBuilderValue_c_1ToString(JNIEnv* env, jclass cls, jlong self) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + CString strValue = pSelf->ToString(); + std::string strUtfData = NSFile::CUtf8Converter::GetUtf8StringFromUnicode2(strValue.c_str(), (LONG)wcslen(strValue.c_str())); + return env->NewStringUTF(strUtfData.c_str()); +} + +jlong Java_docbuilder_CDocBuilderValue_c_1GetProperty(JNIEnv* env, jclass cls, jlong self, jstring name) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + const char* strUtfName = env->GetStringUTFChars(name, nullptr); + CDocBuilderValue* pValue = new CDocBuilderValue(pSelf->Get(strUtfName)); + env->ReleaseStringUTFChars(name, strUtfName); + return reinterpret_cast(pValue); +} + +jlong Java_docbuilder_CDocBuilderValue_c_1GetByIndex(JNIEnv* env, jclass cls, jlong self, jint index) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + CDocBuilderValue* pValue = new CDocBuilderValue(pSelf->Get((int)index)); + return reinterpret_cast(pValue); +} + +void Java_docbuilder_CDocBuilderValue_c_1SetProperty(JNIEnv* env, jclass cls, jlong self, jstring name, jlong value) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + CDocBuilderValue* pValue = reinterpret_cast(value); + const char* strUtfName = env->GetStringUTFChars(name, nullptr); + std::wstring strName = NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)strUtfName, (LONG)strlen(strUtfName)); + pSelf->Set(strName.c_str(), *pValue); + env->ReleaseStringUTFChars(name, strUtfName); +} + +void Java_docbuilder_CDocBuilderValue_c_1SetByIndex(JNIEnv* env, jclass cls, jlong self, jint index, jlong value) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + CDocBuilderValue* pValue = reinterpret_cast(value); + pSelf->Set((int)index, *pValue); +} + +jlong Java_docbuilder_CDocBuilderValue_c_1CreateWithBool(JNIEnv* env, jclass cls, jboolean value) +{ + return reinterpret_cast(new CDocBuilderValue((bool)value)); +} + +jlong Java_docbuilder_CDocBuilderValue_c_1CreateWithInt(JNIEnv* env, jclass cls, jint value) +{ + return reinterpret_cast(new CDocBuilderValue((int)value)); +} + +jlong Java_docbuilder_CDocBuilderValue_c_1CreateWithDouble(JNIEnv* env, jclass cls, jdouble value) +{ + return reinterpret_cast(new CDocBuilderValue((double)value)); +} + +jlong Java_docbuilder_CDocBuilderValue_c_1CreateWithString(JNIEnv* env, jclass cls, jstring str) +{ + const char* strUtf = env->GetStringUTFChars(str, nullptr); + CDocBuilderValue* pValue = new CDocBuilderValue(strUtf); + env->ReleaseStringUTFChars(str, strUtf); + return reinterpret_cast(pValue); +} + +jlong Java_docbuilder_CDocBuilderValue_c_1CreateUndefined(JNIEnv* env, jclass cls) +{ + return reinterpret_cast(new CDocBuilderValue(CDocBuilderValue::CreateUndefined())); +} + +jlong Java_docbuilder_CDocBuilderValue_c_1CreateNull(JNIEnv* env, jclass cls) +{ + return reinterpret_cast(new CDocBuilderValue(CDocBuilderValue::CreateNull())); +} + +jlong Java_docbuilder_CDocBuilderValue_c_1CreateArray(JNIEnv* env, jclass cls, jint length) +{ + return reinterpret_cast(new CDocBuilderValue(CDocBuilderValue::CreateArray((int)length))); +} + +jlong Java_docbuilder_CDocBuilderValue_c_1Call0(JNIEnv* env, jclass cls, jlong self, jstring name) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + const char* strUtfName = env->GetStringUTFChars(name, nullptr); + CDocBuilderValue* pReturnValue = new CDocBuilderValue(pSelf->Call(strUtfName)); + env->ReleaseStringUTFChars(name, strUtfName); + return reinterpret_cast(pReturnValue); +} + +jlong Java_docbuilder_CDocBuilderValue_c_1Call1(JNIEnv* env, jclass cls, jlong self, jstring name, jlong p1) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + CDocBuilderValue* pParam1 = reinterpret_cast(p1); + const char* strUtfName = env->GetStringUTFChars(name, nullptr); + CDocBuilderValue* pReturnValue = new CDocBuilderValue(pSelf->Call(strUtfName, *pParam1)); + env->ReleaseStringUTFChars(name, strUtfName); + return reinterpret_cast(pReturnValue); +} + +jlong Java_docbuilder_CDocBuilderValue_c_1Call2(JNIEnv* env, jclass cls, jlong self, jstring name, jlong p1, jlong p2) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + CDocBuilderValue* pParam1 = reinterpret_cast(p1); + CDocBuilderValue* pParam2 = reinterpret_cast(p2); + const char* strUtfName = env->GetStringUTFChars(name, nullptr); + CDocBuilderValue* pReturnValue = new CDocBuilderValue(pSelf->Call(strUtfName, *pParam1, *pParam2)); + env->ReleaseStringUTFChars(name, strUtfName); + return reinterpret_cast(pReturnValue); +} + +jlong Java_docbuilder_CDocBuilderValue_c_1Call3(JNIEnv* env, jclass cls, jlong self, jstring name, jlong p1, jlong p2, jlong p3) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + CDocBuilderValue* pParam1 = reinterpret_cast(p1); + CDocBuilderValue* pParam2 = reinterpret_cast(p2); + CDocBuilderValue* pParam3 = reinterpret_cast(p3); + const char* strUtfName = env->GetStringUTFChars(name, nullptr); + CDocBuilderValue* pReturnValue = new CDocBuilderValue(pSelf->Call(strUtfName, *pParam1, *pParam2, *pParam3)); + env->ReleaseStringUTFChars(name, strUtfName); + return reinterpret_cast(pReturnValue); +} + +jlong Java_docbuilder_CDocBuilderValue_c_1Call4(JNIEnv* env, jclass cls, jlong self, jstring name, jlong p1, jlong p2, jlong p3, jlong p4) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + CDocBuilderValue* pParam1 = reinterpret_cast(p1); + CDocBuilderValue* pParam2 = reinterpret_cast(p2); + CDocBuilderValue* pParam3 = reinterpret_cast(p3); + CDocBuilderValue* pParam4 = reinterpret_cast(p4); + const char* strUtfName = env->GetStringUTFChars(name, nullptr); + CDocBuilderValue* pReturnValue = new CDocBuilderValue(pSelf->Call(strUtfName, *pParam1, *pParam2, *pParam3, *pParam4)); + env->ReleaseStringUTFChars(name, strUtfName); + return reinterpret_cast(pReturnValue); +} + +jlong Java_docbuilder_CDocBuilderValue_c_1Call5(JNIEnv* env, jclass cls, jlong self, jstring name, jlong p1, jlong p2, jlong p3, jlong p4, jlong p5) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + CDocBuilderValue* pParam1 = reinterpret_cast(p1); + CDocBuilderValue* pParam2 = reinterpret_cast(p2); + CDocBuilderValue* pParam3 = reinterpret_cast(p3); + CDocBuilderValue* pParam4 = reinterpret_cast(p4); + CDocBuilderValue* pParam5 = reinterpret_cast(p5); + const char* strUtfName = env->GetStringUTFChars(name, nullptr); + CDocBuilderValue* pReturnValue = new CDocBuilderValue(pSelf->Call(strUtfName, *pParam1, *pParam2, *pParam3, *pParam4, *pParam5)); + env->ReleaseStringUTFChars(name, strUtfName); + return reinterpret_cast(pReturnValue); +} + +jlong Java_docbuilder_CDocBuilderValue_c_1Call6(JNIEnv* env, jclass cls, jlong self, jstring name, jlong p1, jlong p2, jlong p3, jlong p4, jlong p5, jlong p6) +{ + CDocBuilderValue* pSelf = reinterpret_cast(self); + CDocBuilderValue* pParam1 = reinterpret_cast(p1); + CDocBuilderValue* pParam2 = reinterpret_cast(p2); + CDocBuilderValue* pParam3 = reinterpret_cast(p3); + CDocBuilderValue* pParam4 = reinterpret_cast(p4); + CDocBuilderValue* pParam5 = reinterpret_cast(p5); + CDocBuilderValue* pParam6 = reinterpret_cast(p6); + const char* strUtfName = env->GetStringUTFChars(name, nullptr); + CDocBuilderValue* pReturnValue = new CDocBuilderValue(pSelf->Call(strUtfName, *pParam1, *pParam2, *pParam3, *pParam4, *pParam5, *pParam6)); + env->ReleaseStringUTFChars(name, strUtfName); + return reinterpret_cast(pReturnValue); +} diff --git a/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilderValue.h b/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilderValue.h new file mode 100644 index 0000000000..2e0c8e4eb0 --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_CDocBuilderValue.h @@ -0,0 +1,301 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class docbuilder_CDocBuilderValue */ + +#ifndef _Included_docbuilder_CDocBuilderValue +#define _Included_docbuilder_CDocBuilderValue +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_Create + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderValue_c_1Create + (JNIEnv *, jclass); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_Copy + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderValue_c_1Copy + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_Destroy + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_docbuilder_CDocBuilderValue_c_1Destroy + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_IsEmpty + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_docbuilder_CDocBuilderValue_c_1IsEmpty + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_Clear + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_docbuilder_CDocBuilderValue_c_1Clear + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_IsNull + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_docbuilder_CDocBuilderValue_c_1IsNull + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_IsUndefined + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_docbuilder_CDocBuilderValue_c_1IsUndefined + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_IsInt + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_docbuilder_CDocBuilderValue_c_1IsInt + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_IsDouble + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_docbuilder_CDocBuilderValue_c_1IsDouble + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_IsString + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_docbuilder_CDocBuilderValue_c_1IsString + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_IsFunction + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_docbuilder_CDocBuilderValue_c_1IsFunction + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_IsObject + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_docbuilder_CDocBuilderValue_c_1IsObject + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_IsArray + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_docbuilder_CDocBuilderValue_c_1IsArray + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_GetLength + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_docbuilder_CDocBuilderValue_c_1GetLength + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_ToBool + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_docbuilder_CDocBuilderValue_c_1ToBool + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_ToInt + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_docbuilder_CDocBuilderValue_c_1ToInt + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_ToDouble + * Signature: (J)D + */ +JNIEXPORT jdouble JNICALL Java_docbuilder_CDocBuilderValue_c_1ToDouble + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_ToString + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_docbuilder_CDocBuilderValue_c_1ToString + (JNIEnv *, jclass, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_GetProperty + * Signature: (JLjava/lang/String;)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderValue_c_1GetProperty + (JNIEnv *, jclass, jlong, jstring); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_GetByIndex + * Signature: (JI)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderValue_c_1GetByIndex + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_SetProperty + * Signature: (JLjava/lang/String;J)V + */ +JNIEXPORT void JNICALL Java_docbuilder_CDocBuilderValue_c_1SetProperty + (JNIEnv *, jclass, jlong, jstring, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_SetByIndex + * Signature: (JIJ)V + */ +JNIEXPORT void JNICALL Java_docbuilder_CDocBuilderValue_c_1SetByIndex + (JNIEnv *, jclass, jlong, jint, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_CreateWithBool + * Signature: (Z)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderValue_c_1CreateWithBool + (JNIEnv *, jclass, jboolean); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_CreateWithInt + * Signature: (I)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderValue_c_1CreateWithInt + (JNIEnv *, jclass, jint); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_CreateWithDouble + * Signature: (D)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderValue_c_1CreateWithDouble + (JNIEnv *, jclass, jdouble); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_CreateWithString + * Signature: (Ljava/lang/String;)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderValue_c_1CreateWithString + (JNIEnv *, jclass, jstring); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_CreateUndefined + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderValue_c_1CreateUndefined + (JNIEnv *, jclass); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_CreateNull + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderValue_c_1CreateNull + (JNIEnv *, jclass); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_CreateArray + * Signature: (I)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderValue_c_1CreateArray + (JNIEnv *, jclass, jint); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_Call0 + * Signature: (JLjava/lang/String;)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderValue_c_1Call0 + (JNIEnv *, jclass, jlong, jstring); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_Call1 + * Signature: (JLjava/lang/String;J)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderValue_c_1Call1 + (JNIEnv *, jclass, jlong, jstring, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_Call2 + * Signature: (JLjava/lang/String;JJ)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderValue_c_1Call2 + (JNIEnv *, jclass, jlong, jstring, jlong, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_Call3 + * Signature: (JLjava/lang/String;JJJ)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderValue_c_1Call3 + (JNIEnv *, jclass, jlong, jstring, jlong, jlong, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_Call4 + * Signature: (JLjava/lang/String;JJJJ)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderValue_c_1Call4 + (JNIEnv *, jclass, jlong, jstring, jlong, jlong, jlong, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_Call5 + * Signature: (JLjava/lang/String;JJJJJ)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderValue_c_1Call5 + (JNIEnv *, jclass, jlong, jstring, jlong, jlong, jlong, jlong, jlong); + +/* + * Class: docbuilder_CDocBuilderValue + * Method: c_Call6 + * Signature: (JLjava/lang/String;JJJJJJ)J + */ +JNIEXPORT jlong JNICALL Java_docbuilder_CDocBuilderValue_c_1Call6 + (JNIEnv *, jclass, jlong, jstring, jlong, jlong, jlong, jlong, jlong, jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_jni.pro b/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_jni.pro new file mode 100644 index 0000000000..6fe624560f --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/src/jni/docbuilder_jni.pro @@ -0,0 +1,42 @@ +QT -= core +QT -= gui + +TARGET = docbuilder.jni + +TEMPLATE = lib + +CONFIG += shared +CONFIG += plugin + +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(graphics, kernel, kernel_network, UnicodeConverter, doctrenderer) + +INCLUDEPATH += ../../.. + +# Specify JDK path here +JDK_PATH = "C:/Program Files/Java/jdk-22" + +INCLUDEPATH += $$JDK_PATH/include + +core_windows:JAVA_ARCH = win32 +core_linux:JAVA_ARCH = linux +core_mac:JAVA_ARCH = darwin + +INCLUDEPATH += $$JDK_PATH/include/$$JAVA_ARCH + +SOURCES += \ + docbuilder_CDocBuilderValue.cpp \ + docbuilder_CDocBuilder.cpp \ + docbuilder_CDocBuilderContextScope.cpp \ + docbuilder_CDocBuilderContext.cpp + +HEADERS += \ + docbuilder_CDocBuilderValue.h \ + docbuilder_CDocBuilder.h \ + docbuilder_CDocBuilderContextScope.h \ + docbuilder_CDocBuilderContext.h diff --git a/DesktopEditor/doctrenderer/docbuilder.java/test/Program.java b/DesktopEditor/doctrenderer/docbuilder.java/test/Program.java new file mode 100644 index 0000000000..ce734e5f03 --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/test/Program.java @@ -0,0 +1,44 @@ +import docbuilder.*; + +public class Program { + public static void main(String[] args) { + String resultPath = "result.docx"; + + test(resultPath); + + // Need to explicitly call System.gc() because finalizers might not automatically get called + // Note: Even System.gc() can not guarantee that finalizers will be actually called. Possible memory leaks! + System.gc(); + } + + public static void test(String resultPath) { + CDocBuilder.initialize(""); + CDocBuilder builder = new CDocBuilder(); + builder.createFile(FileTypes.Document.DOCX); + + CDocBuilderContext context = builder.getContext(); + CDocBuilderContextScope scope = context.createScope(); + + CDocBuilderValue global = context.getGlobal(); + + CDocBuilderValue api = global.get("Api"); + CDocBuilderValue document = api.call("GetDocument"); + CDocBuilderValue paragraph1 = api.call("CreateParagraph"); + + paragraph1.call("SetSpacingAfter", 1000, false); + paragraph1.call("AddText", "Hello from Java!"); + + CDocBuilderValue paragraph2 = api.call("CreateParagraph"); + paragraph2.call("AddText", "Goodbye!"); + + CDocBuilderValue[] paragraphs = { paragraph1, paragraph2 }; + CDocBuilderValue content = new CDocBuilderValue(paragraphs); + + document.call("InsertContent", content); + + builder.saveFile(FileTypes.Document.DOCX, resultPath); + builder.closeFile(); + + CDocBuilder.dispose(); + } +} diff --git a/DesktopEditor/doctrenderer/docbuilder.java/test/make_test.py b/DesktopEditor/doctrenderer/docbuilder.java/test/make_test.py new file mode 100644 index 0000000000..9af45c86a1 --- /dev/null +++ b/DesktopEditor/doctrenderer/docbuilder.java/test/make_test.py @@ -0,0 +1,29 @@ +import os +import argparse + +# NOTE: In JDK 8 and earlier, `javac` does not create the directories specified in the -d option if they do not already exist +# So we need to create them manually +def makedirs(dir): + if not os.path.exists(dir): + os.makedirs(dir) + return + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Build and run the test example for docbuilder Java wrapper') + parser.add_argument('-r', '--run', dest='builder_dir', metavar='', help='Run the test example with specified docbuilder directory') + args = parser.parse_args() + + file_dir = os.path.dirname(os.path.realpath(__file__)); + os.chdir(file_dir) + + java_file = 'Program.java' + + if args.builder_dir: + builder_dir = args.builder_dir + os.system('java -cp ' + builder_dir + '/docbuilder.jar' + os.pathsep + 'build/classes Program') + else: + makedirs('build/classes') + os.system('javac -d build/classes -cp ../build/libs/docbuilder.jar ' + java_file) + print('Program was built successfully') + print('Run it with: java -cp \"/path/to/docbuilder/docbuilder.jar' + os.pathsep + 'build/classes\" Program') + print('Or just run: python make_test.py --run \"/path/to/docbuilder\"') diff --git a/DesktopEditor/doctrenderer/docbuilder.python/src/docbuilder_functions.cpp b/DesktopEditor/doctrenderer/docbuilder.python/src/docbuilder_functions.cpp index 24bb38523f..6df39de00e 100644 --- a/DesktopEditor/doctrenderer/docbuilder.python/src/docbuilder_functions.cpp +++ b/DesktopEditor/doctrenderer/docbuilder.python/src/docbuilder_functions.cpp @@ -95,7 +95,7 @@ const wchar_t* CDocBuilderValue_ToString(CDocBuilderValue* self) CString strValue = self->ToString(); size_t len = wcslen(strValue.c_str()); wchar_t* strRes = new wchar_t[len + 1]; - memcpy(strRes, strValue.c_str(), (len + 1) + sizeof(wchar_t)); + memcpy(strRes, strValue.c_str(), (len + 1) * sizeof(wchar_t)); return strRes; } diff --git a/DesktopEditor/graphics/AlphaMask.cpp b/DesktopEditor/graphics/AlphaMask.cpp index 1bda9d866f..6c3acb342b 100644 --- a/DesktopEditor/graphics/AlphaMask.cpp +++ b/DesktopEditor/graphics/AlphaMask.cpp @@ -37,11 +37,6 @@ namespace Aggplus } } - void CAlphaMask::SetDataType(EMaskDataType oType) - { - m_enDataType = oType; - } - Status CAlphaMask::Create(UINT unWidth, UINT unHeight, EMaskDataType eDataType) { if (0 == unWidth || 0 == unHeight) @@ -69,4 +64,140 @@ namespace Aggplus m_bExternalBuffer = bExternalBuffer; return Ok; } + + + + CSoftMask::CSoftMask() : m_pImageData(NULL), m_pAlphaBufferData(NULL), m_unWidth(0), m_unHeight(0) {} + CSoftMask::CSoftMask(BYTE* pBuffer, UINT unWidth, UINT unHeight, EMaskDataType enDataType, bool bExternalBuffer, bool bFlip) + { + m_pImageData = NULL; + m_pAlphaBufferData = NULL; + + LoadFromBuffer(pBuffer, unWidth, unHeight, enDataType, bExternalBuffer, bFlip); + } + CSoftMask::~CSoftMask() + { + BYTE *pBuffer = m_oRenderingBuffer.buf(); + if (NULL != pBuffer) + { + if (!m_bExternalBuffer) + RELEASEARRAYOBJECTS(pBuffer); + + m_oRenderingBuffer.attach(NULL, 0, 0, 0); + } + + RELEASEOBJECT(m_pImageData); + RELEASEOBJECT(m_pAlphaBufferData); + } + + EMaskDataType CSoftMask::GetDataType() const { return m_enDataType; } + unsigned int CSoftMask::GetStep() const + { + switch(m_enDataType) + { + case EMaskDataType::ImageBuffer: return 4; + case EMaskDataType::AlphaBuffer: return 1; + case EMaskDataType::Alpha4Buffer: return 4; + } + } + unsigned int CSoftMask::GetWidth() const + { + return m_unWidth; + } + unsigned int CSoftMask::GetHeight() const + { + return m_unHeight; + } + + void CSoftMask::SetType(EMaskDataType enDataType) + { + m_enDataType = enDataType; + + RELEASEOBJECT(m_pImageData); + RELEASEOBJECT(m_pAlphaBufferData); + + switch (enDataType) + { + case EMaskDataType::ImageBuffer: + { + m_pImageData = new AMaskFromImage(m_oRenderingBuffer); + m_pImageData->m_oRendererBase.attach(m_pImageData->m_oPixfmt); + m_pImageData->m_oAlphaMask.attach(m_oRenderingBuffer); + break; + } + case EMaskDataType::Alpha4Buffer: + { + m_pAlphaBufferData = new AMaskFromABuffer(m_oRenderingBuffer); + m_pAlphaBufferData->m_oRendererBase.attach(m_pAlphaBufferData->m_oPixfmt); + m_pAlphaBufferData->m_oAlphaMask.attach(m_oRenderingBuffer); + break; + } + } + } + + Status CSoftMask::Create(UINT unWidth, UINT unHeight, EMaskDataType enDataType) + { + if (0 == unWidth || 0 == unHeight) + return InvalidParameter; + + m_bExternalBuffer = false; + + UINT unSize = unWidth * unHeight * GetStep(); + BYTE* pAlphaBufffer = new BYTE[unSize]; + if (!pAlphaBufffer) + return OutOfMemory; + + memset(pAlphaBufffer, 0x00, unSize); + + Set(pAlphaBufffer, unWidth, unHeight, enDataType); + + return Ok; + } + + Status CSoftMask::LoadFromBuffer(BYTE *pBuffer, UINT unWidth, UINT unHeight, EMaskDataType enDataType, bool bExternalBuffer, bool bFlip) + { + if (NULL == pBuffer || 0 == unWidth || 0 == unHeight) + return InvalidParameter; + + m_bExternalBuffer = bExternalBuffer; + + Set(pBuffer, unWidth, unHeight, enDataType, bFlip); + + return Ok; + } + + RenBaseBGRA32& CSoftMask::GetRendererBaseImage() + { + return m_pImageData->m_oRendererBase; + } + + ScanlineBGRA32Gray& CSoftMask::GetScanlineImage() + { + return m_pImageData->m_oScanLine; + } + + ScanlineBGRA32A& CSoftMask::GetScanlineABuffer() + { + return m_pAlphaBufferData->m_oScanLine; + } + + BYTE* CSoftMask::GetBuffer() + { + return m_oRenderingBuffer.buf(); + } + + agg::rendering_buffer& CSoftMask::GetRenderingBuffer() + { + return m_oRenderingBuffer; + } + + void CSoftMask::Set(BYTE* pBuffer, UINT unWidth, UINT unHeight, EMaskDataType enDataType, bool bFlip) + { + m_enDataType = enDataType; + m_unWidth = unWidth; + m_unHeight = unHeight; + m_oRenderingBuffer.attach(pBuffer, unWidth, unHeight, (bFlip ? -1 : 1) * GetStep() * unWidth); + + SetType(enDataType); + } } diff --git a/DesktopEditor/graphics/AlphaMask.h b/DesktopEditor/graphics/AlphaMask.h index 8d4b18a744..273d0d3361 100644 --- a/DesktopEditor/graphics/AlphaMask.h +++ b/DesktopEditor/graphics/AlphaMask.h @@ -6,6 +6,11 @@ #include "../common/IGrObject.h" #include "./config.h" +#include "../agg-2.4/include/agg_renderer_base.h" +#include "../agg-2.4/include/agg_pixfmt_rgba.h" +#include "../agg-2.4/include/agg_scanline_u.h" +#include "../agg-2.4/include/agg_alpha_mask_u8.h" + namespace Aggplus { enum class EMaskDataType @@ -26,7 +31,6 @@ namespace Aggplus EMaskDataType GetDataType() const; UINT GetStep() const; - void SetDataType(EMaskDataType oType); Status Create(UINT unWidth, UINT unHeight, EMaskDataType eDataType); Status LoadFromBuffer(BYTE* pBuffer, EMaskDataType eDataType, bool bExternalBuffer = true); private: @@ -34,6 +38,58 @@ namespace Aggplus EMaskDataType m_enDataType; bool m_bExternalBuffer; }; + + template + struct TAlphaMaskData + { + TAlphaMaskData(agg::rendering_buffer& oRenderingBuffer) : m_oPixfmt(oRenderingBuffer), m_oScanLine(m_oAlphaMask) {}; + + PixelFormat m_oPixfmt; + agg::renderer_base m_oRendererBase; + AlphaMask m_oAlphaMask; + agg::scanline_u8_am m_oScanLine; + }; + + typedef agg::renderer_base RenBaseBGRA32; + typedef agg::scanline_u8_am ScanlineBGRA32Gray; + typedef agg::scanline_u8_am ScanlineBGRA32A; + + class GRAPHICS_DECL CSoftMask : public IGrObject + { + public: + CSoftMask(); + CSoftMask(BYTE* pBuffer, UINT unWidth, UINT unHeight, EMaskDataType enDataType, bool bExternalBuffer = true, bool bFlip = false); + virtual ~CSoftMask(); + + EMaskDataType GetDataType() const; + unsigned int GetStep() const; + unsigned int GetWidth() const; + unsigned int GetHeight() const; + + void SetType(EMaskDataType enDataType); + Status Create(UINT unWidth, UINT unHeight, EMaskDataType enDataType); + Status LoadFromBuffer(BYTE* pBuffer, UINT unWidth, UINT unHeight, EMaskDataType enDataType, bool bExternalBuffer = true, bool bFlip = false); + + agg::rendering_buffer& GetRenderingBuffer(); + RenBaseBGRA32& GetRendererBaseImage(); + ScanlineBGRA32Gray& GetScanlineImage(); + ScanlineBGRA32A& GetScanlineABuffer(); + BYTE* GetBuffer(); + private: + void Set(BYTE* pBuffer, UINT unWidth, UINT unHeight, EMaskDataType enDataType, bool bFlip = false); + + agg::rendering_buffer m_oRenderingBuffer; + EMaskDataType m_enDataType; + bool m_bExternalBuffer; + unsigned int m_unWidth; + unsigned int m_unHeight; + + typedef TAlphaMaskData AMaskFromImage; + typedef TAlphaMaskData AMaskFromABuffer; + + AMaskFromImage* m_pImageData; + AMaskFromABuffer* m_pAlphaBufferData; + }; } #endif // _BUILD_ALPHAMASK_H_ diff --git a/DesktopEditor/graphics/Graphics.cpp b/DesktopEditor/graphics/Graphics.cpp index 5c2061a1f2..e83ae9cda8 100644 --- a/DesktopEditor/graphics/Graphics.cpp +++ b/DesktopEditor/graphics/Graphics.cpp @@ -68,6 +68,7 @@ namespace Aggplus m_dDpiTile = -1; m_pAlphaMask = NULL; + m_pSoftMask = NULL; m_nTextRenderMode = FT_RENDER_MODE_NORMAL; m_nBlendMode = agg::comp_op_src_over; @@ -106,6 +107,7 @@ namespace Aggplus m_dDpiTile = -1; m_pAlphaMask = NULL; + m_pSoftMask = NULL; m_nTextRenderMode = FT_RENDER_MODE_NORMAL; m_nBlendMode = agg::comp_op_src_over; @@ -149,6 +151,7 @@ namespace Aggplus m_dDpiTile = -1; m_pAlphaMask = NULL; + m_pSoftMask = NULL; m_nTextRenderMode = FT_RENDER_MODE_NORMAL; m_nBlendMode = agg::comp_op_src_over; @@ -164,6 +167,7 @@ namespace Aggplus #endif RELEASEINTERFACE(m_pAlphaMask); + RELEASEINTERFACE(m_pSoftMask); while (!m_arLayers.empty()) { @@ -1236,9 +1240,7 @@ namespace Aggplus if (m_pAlphaMask) m_pAlphaMask->AddRef(); - return Ok; - - //return CreateLayer(); + return CreateLayer(); } Status CGraphics::StartCreatingAlphaMask() @@ -1275,6 +1277,54 @@ namespace Aggplus return Ok; } + CSoftMask* CGraphics::CreateSoftMask(bool bAlpha) + { + if (m_arLayers.empty()) + return NULL; + + CGraphicsLayer *pCurrentGraphicsLayer = m_arLayers.top(); + m_arLayers.pop(); + + if (pCurrentGraphicsLayer->Empty()) + { + RELEASEINTERFACE(pCurrentGraphicsLayer); + return NULL; + } + + BYTE* pBuffer = pCurrentGraphicsLayer->GetBuffer(); + pCurrentGraphicsLayer->ClearBuffer(false); + + RELEASEINTERFACE(pCurrentGraphicsLayer); + RELEASEINTERFACE(m_pSoftMask); + + m_pSoftMask = new CSoftMask(pBuffer, m_frame_buffer.ren_buf().width(), m_frame_buffer.ren_buf().height(), bAlpha ? EMaskDataType::Alpha4Buffer : EMaskDataType::ImageBuffer, false, m_frame_buffer.ren_buf().stride() < 0); + + pBuffer = m_arLayers.empty() ? m_pPixels : m_arLayers.top()->GetBuffer(); + if (!pBuffer) + { + RELEASEINTERFACE(pCurrentGraphicsLayer); + return NULL; + } + + m_frame_buffer.ren_buf().attach(pBuffer, m_frame_buffer.ren_buf().width(), m_frame_buffer.ren_buf().height(), m_frame_buffer.ren_buf().stride()); + + return m_pSoftMask; + } + + Status CGraphics::SetSoftMask(CSoftMask* pSoftMask) + { + if (m_pSoftMask == pSoftMask) + return Ok; + + RELEASEINTERFACE(m_pSoftMask); + m_pSoftMask = pSoftMask; + + if (m_pSoftMask) + m_pSoftMask->AddRef(); + + return Ok; + } + Status CGraphics::AddLayer(CGraphicsLayer *pGraphicsLayer) { if (NULL == pGraphicsLayer || pGraphicsLayer->Empty()) @@ -1287,7 +1337,7 @@ namespace Aggplus 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()); + m_frame_buffer.create(unWidth, unHeight, nStride < 0, nStride, pGraphicsLayer->GetBuffer()); return Ok; } @@ -1304,7 +1354,7 @@ namespace Aggplus memset(pBuffer, 0x00, unSize); - m_frame_buffer.create(unWidth, unHeight, false, nStride, pBuffer); + m_frame_buffer.create(unWidth, unHeight, nStride < 0, nStride, pBuffer); m_arLayers.push(new CGraphicsLayer(pBuffer, false)); return Ok; @@ -1333,9 +1383,41 @@ namespace Aggplus m_frame_buffer.ren_buf().attach(pBuffer, m_frame_buffer.ren_buf().width(), m_frame_buffer.ren_buf().height(), m_frame_buffer.ren_buf().stride()); - if (NULL == m_pAlphaMask) + if (m_pAlphaMask) { - if (m_nBlendMode != agg::comp_op_src_over)// && m_nBlendMode != agg::comp_op_multiply && m_nBlendMode != agg::comp_op_screen && m_nBlendMode != agg::comp_op_darken) + switch(m_pAlphaMask->GetDataType()) + { + case EMaskDataType::ImageBuffer: + { + Aggplus::BlendTo>(pCurrentGraphicsLayer, m_frame_buffer.pixfmt(), m_pAlphaMask->GetBuffer(), m_pAlphaMask->GetStep()); + break; + } + case EMaskDataType::AlphaBuffer: + { + Aggplus::BlendTo(pCurrentGraphicsLayer, m_frame_buffer.pixfmt(), m_pAlphaMask->GetBuffer(), m_pAlphaMask->GetStep()); + break; + } + } + } + else if (m_pSoftMask) + { + switch(m_pSoftMask->GetDataType()) + { + case EMaskDataType::ImageBuffer: + { + Aggplus::BlendTo>(pCurrentGraphicsLayer, m_frame_buffer.pixfmt(), m_pSoftMask->GetBuffer(), m_pSoftMask->GetStep()); + break; + } + case EMaskDataType::Alpha4Buffer: + { + Aggplus::BlendTo(pCurrentGraphicsLayer, m_frame_buffer.pixfmt(), m_pSoftMask->GetBuffer() + 3, m_pSoftMask->GetStep()); + break; + } + } + } + else + { + if (m_nBlendMode != agg::comp_op_src_over) { pixfmt_type_comp pixfmt(m_frame_buffer.ren_buf(), m_nBlendMode); Aggplus::BlendTo(pCurrentGraphicsLayer, pixfmt, m_nBlendMode); @@ -1343,27 +1425,6 @@ namespace Aggplus else Aggplus::BlendTo(pCurrentGraphicsLayer, m_frame_buffer.pixfmt()); } - else - { - switch(m_pAlphaMask->GetDataType()) - { - case EMaskDataType::ImageBuffer: - { - Aggplus::BlendTo>(pCurrentGraphicsLayer, m_frame_buffer.pixfmt(), m_pAlphaMask->GetBuffer(), m_pAlphaMask->GetStep()); - break; - } - case EMaskDataType::AlphaBuffer: - { - Aggplus::BlendTo(pCurrentGraphicsLayer, m_frame_buffer.pixfmt(), m_pAlphaMask->GetBuffer(), m_pAlphaMask->GetStep()); - break; - } - case EMaskDataType::Alpha4Buffer: - { - Aggplus::BlendTo(pCurrentGraphicsLayer, m_frame_buffer.pixfmt(), m_pAlphaMask->GetBuffer(), m_pAlphaMask->GetStep()); - break; - } - } - } RELEASEINTERFACE(pCurrentGraphicsLayer); return Ok; @@ -1377,6 +1438,21 @@ namespace Aggplus 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; + } + + m_frame_buffer.ren_buf().attach(pBuffer, m_frame_buffer.ren_buf().width(), m_frame_buffer.ren_buf().height(), m_frame_buffer.ren_buf().stride()); + RELEASEINTERFACE(pCurrentGraphicsLayer); return Ok; } @@ -1404,54 +1480,6 @@ namespace Aggplus return Ok; } - Status CGraphics::SetLayerIsolated(bool bIsolated) - { - if (m_arLayers.empty()) - return WrongState; - - UINT unSize = m_frame_buffer.ren_buf().width() * m_frame_buffer.ren_buf().height() * m_frame_buffer.pix_size; - if (bIsolated) - memset(m_arLayers.top()->GetBuffer(), 0x00, unSize); - else - memcpy(m_arLayers.top()->GetBuffer(), m_pPixels, unSize); - - return Ok; - } - - Status CGraphics::SetAlphaMaskIsolated(bool bIsolated) - { - if (m_arLayers.empty()) - return WrongState; - - UINT unSize = m_frame_buffer.ren_buf().width() * m_frame_buffer.ren_buf().height() * m_frame_buffer.pix_size; - if (bIsolated) - { - memset(m_arLayers.top()->GetBuffer(), 0x00, unSize); - } - else - { - BYTE* pBuffer = m_arLayers.top()->GetBuffer(); - for (unsigned int i = 0; i < unSize; i = i + 4) - { - pBuffer[i + 0] = 0x00; - pBuffer[i + 1] = 0x00; - pBuffer[i + 2] = 0x00; - pBuffer[i + 3] = 0xFF; - } - } - - return Ok; - } - - Status CGraphics::SetAlphaMaskType(EMaskDataType oType) - { - if (!m_pAlphaMask) - return WrongState; - - m_pAlphaMask->SetDataType(oType); - return Ok; - } - void CGraphics::CalculateFullTransform() { m_oFullTransform = m_oCoordTransform; @@ -1463,52 +1491,43 @@ namespace Aggplus return m_oClip.IsClip(); } - unsigned int CGraphics::GetLayerW() - { - return m_frame_buffer.ren_buf().width(); - } - - unsigned int CGraphics::GetLayerH() - { - return m_frame_buffer.ren_buf().height(); - } - - template - void CGraphics::render_scanlines(Renderer& ren) + template + void CGraphics::render_scanlines_3(Rasterizer& ras, Renderer& ren, Scanline& sl) { if (!m_oClip.IsClip()) { - agg::render_scanlines(m_rasterizer.get_rasterizer(), m_rasterizer.get_scanline(), ren); + agg::render_scanlines(ras, sl, ren); } else { if (!m_oClip.IsClip2()) { - typedef agg::scanline_p8 sbool_scanline_type; + typedef agg::scanline_p8 sbool_scanline_type; - sbool_scanline_type sl_result; sbool_scanline_type sl1; sbool_scanline_type sl2; - agg::sbool_combine_shapes_aa(agg::sbool_and, m_rasterizer.get_rasterizer(), m_oClip.m_rasterizer, - sl1, sl2, sl_result, ren); + agg::sbool_combine_shapes_aa(agg::sbool_and, ras, m_oClip.m_rasterizer, sl1, sl2, sl, ren); } else { - typedef agg::scanline_p8 sbool_scanline_type; - sbool_scanline_type sl_result; + typedef agg::scanline_p8 sbool_scanline_type; + sbool_scanline_type sl1; sbool_scanline_type sl2; - sbool_scanline_type sl; - - agg::sbool_combine_shapes_aa(agg::sbool_and, m_rasterizer.get_rasterizer(), - (1 == m_oClip.m_lCurStorage) ? m_oClip.m_storage1 : m_oClip.m_storage2, sl1, sl2, sl_result, ren); + agg::sbool_combine_shapes_aa(agg::sbool_and, ras, (1 == m_oClip.m_lCurStorage) ? m_oClip.m_storage1 : m_oClip.m_storage2, sl1, sl2, sl, ren); } } } + template + void CGraphics::render_scanlines(Renderer& ren) + { + render_scanlines_2(m_rasterizer.get_rasterizer(), ren); + } + template void CGraphics::render_scanlines_alpha(Renderer& ren, BYTE Alpha) { @@ -1526,47 +1545,16 @@ namespace Aggplus } template - void CGraphics::render_scanlines(Rasterizer& ras, Renderer& ren) + void CGraphics::render_scanlines_2(Rasterizer& ras, Renderer& ren) { - if (!m_oClip.IsClip()) + if (m_pSoftMask) { -// if (m_pAlphaMask && ApplyingAlphaMask == m_pAlphaMask->GetStatus()) -// { -// if (ImageBuffer == m_pAlphaMask->GetDataType()) -// return agg::render_scanlines(ras, m_pAlphaMask->m_internal->GetScanlineImage(), ren); -// else if (AlphaBuffer == m_pAlphaMask->GetDataType()) -// return agg::render_scanlines(ras, m_pAlphaMask->m_internal->GetScanlineABuffer(), ren); -// } - - return agg::render_scanlines(ras, m_rasterizer.get_scanline(), ren); - } - else - { - if (!m_oClip.IsClip2()) - { - typedef agg::scanline_p8 sbool_scanline_type; - - sbool_scanline_type sl_result; - sbool_scanline_type sl1; - sbool_scanline_type sl2; - - agg::sbool_combine_shapes_aa(agg::sbool_and, ras, m_oClip.m_rasterizer, - sl1, sl2, sl_result, ren); - } - else - { - typedef agg::scanline_p8 sbool_scanline_type; - - sbool_scanline_type sl_result; - sbool_scanline_type sl1; - sbool_scanline_type sl2; - - sbool_scanline_type sl; - - agg::sbool_combine_shapes_aa(agg::sbool_and, ras, - (1 == m_oClip.m_lCurStorage) ? m_oClip.m_storage1 : m_oClip.m_storage2, sl1, sl2, sl_result, ren); - } + if (m_pSoftMask->GetDataType() == EMaskDataType::ImageBuffer) + return render_scanlines_3(ras, ren, m_pSoftMask->GetScanlineImage()); + if (m_pSoftMask->GetDataType() == EMaskDataType::Alpha4Buffer) + return render_scanlines_3(ras, ren, m_pSoftMask->GetScanlineABuffer()); } + render_scanlines_3(ras, ren, m_rasterizer.get_scanline()); } void CGraphics::DoFillPathSolid(CColor dwColor) @@ -2304,7 +2292,7 @@ namespace Aggplus ren_fine.color(clr.GetAggColor()); //agg::render_scanlines(storage, m_rasterizer.get_scanline(), ren_fine); - render_scanlines(storage, ren_fine); + render_scanlines_2(storage, ren_fine); } return 0; diff --git a/DesktopEditor/graphics/Graphics.h b/DesktopEditor/graphics/Graphics.h index 69c570c0eb..710f52fffa 100644 --- a/DesktopEditor/graphics/Graphics.h +++ b/DesktopEditor/graphics/Graphics.h @@ -282,6 +282,7 @@ protected: CClipMulti m_oClip; CAlphaMask* m_pAlphaMask; + CSoftMask* m_pSoftMask; std::stack m_arLayers; @@ -402,11 +403,13 @@ public: //Работа с альфа-маской Status SetAlphaMask(CAlphaMask* pAlphaMask); - inline CAlphaMask* GetAlphaMask() { return m_pAlphaMask; } Status StartCreatingAlphaMask(); Status EndCreatingAlphaMask(); Status ResetAlphaMask(); + CSoftMask* CreateSoftMask(bool bAlpha); + Status SetSoftMask(CSoftMask* pSoftMask); + //Работа со слоями Status AddLayer(CGraphicsLayer* pGraphicsLayer); Status CreateLayer(); @@ -415,9 +418,6 @@ public: Status SetLayerSettings(const TGraphicsLayerSettings& oSettings); Status SetLayerOpacity(double dOpacity); - Status SetLayerIsolated(bool bIsolated); - Status SetAlphaMaskIsolated(bool bIsolated); - Status SetAlphaMaskType(EMaskDataType oType); void CalculateFullTransform(); bool IsClip(); @@ -427,17 +427,17 @@ public: inline double GetPixW() { return m_dWidthPix; } inline double GetPixH() { return m_dHeightPix; } - unsigned int GetLayerW(); - unsigned int GetLayerH(); protected: template void render_scanlines(Renderer& ren); template - void render_scanlines(Rasterizer& ras, Renderer& ren); + void render_scanlines_2(Rasterizer& ras, Renderer& ren); template void render_scanlines_alpha(Renderer& ren, BYTE Alpha); + template + void render_scanlines_3(Rasterizer& ras, Renderer& ren, Scanline& sl); void DoFillPathSolid(CColor dwColor); void DoFillPathGradient(CBrushLinearGradient *pBrush); diff --git a/DesktopEditor/graphics/GraphicsLayerBlend.h b/DesktopEditor/graphics/GraphicsLayerBlend.h index 7fae237428..65a8dfdea2 100644 --- a/DesktopEditor/graphics/GraphicsLayerBlend.h +++ b/DesktopEditor/graphics/GraphicsLayerBlend.h @@ -23,11 +23,11 @@ namespace Aggplus unsigned int unSrcH = oSrc.height(); BYTE nOpacity = pLayer->GetSettings().m_uchOpacity; - bool bStride = oSrc.stride() < 0; + bool bFlip = oSrc.stride() < 0; for (unsigned int unY = 0; unY < unSrcH; ++unY) { - pDstBuffer = oSrc.row_ptr(bStride ? unSrcH - unY - 1: unY); + pDstBuffer = oSrc.row_ptr(bFlip ? unSrcH - 1 - unY : unY); for (unsigned int unX = 0; unX < unSrcW; ++unX) { uchAlpha = (SrcPixelFormatRenderer::base_mask + nOpacity * pSrcBuffer[order_type::A]) >> 8; @@ -70,11 +70,11 @@ namespace Aggplus unsigned int unSrcH = oSrc.height(); BYTE nOpacity = pLayer->GetSettings().m_uchOpacity; - bool bStride = oSrc.stride() < 0; + bool bFlip = oSrc.stride() < 0; for (unsigned int unY = 0; unY < unSrcH; ++unY) { - pDstBuffer = oSrc.row_ptr(bStride ? unSrcH - unY - 1: unY); + pDstBuffer = oSrc.row_ptr(bFlip ? unSrcH - 1 - unY : unY); for (unsigned int unX = 0; unX < unSrcW; ++unX) { uchAlpha = (SrcPixelFormatRenderer::base_mask + nOpacity * pSrcBuffer[order_type::A]) >> 8; @@ -108,11 +108,11 @@ namespace Aggplus unsigned int unSrcH = oSrc.height(); BYTE nOpacity = pLayer->GetSettings().m_uchOpacity; - bool bStride = oSrc.stride() < 0; + bool bFlip = oSrc.stride() < 0; for (unsigned int unY = 0; unY < unSrcH; ++unY) { - pDstBuffer = oSrc.row_ptr(bStride ? unSrcH - unY - 1: unY); + pDstBuffer = oSrc.row_ptr(bFlip ? unSrcH - 1 - unY : unY); for (unsigned int unX = 0; unX < unSrcW; ++unX) { uchAlpha = ((SrcPixelFormatRenderer::base_mask + nOpacity * pSrcBuffer[order_type::A] * AlphaMaskFunction::calculate(pSrcAlphaMaskBuffer)) >> 16); diff --git a/DesktopEditor/graphics/GraphicsRenderer.cpp b/DesktopEditor/graphics/GraphicsRenderer.cpp index d0eb20a07b..a2798d3ffe 100644 --- a/DesktopEditor/graphics/GraphicsRenderer.cpp +++ b/DesktopEditor/graphics/GraphicsRenderer.cpp @@ -1416,9 +1416,14 @@ void CGraphicsRenderer::SetAlphaMask(Aggplus::CAlphaMask *pAlphaMask) m_pRenderer->SetAlphaMask(pAlphaMask); } -Aggplus::CAlphaMask* CGraphicsRenderer::GetAlphaMask() +Aggplus::CSoftMask* CGraphicsRenderer::CreateSoftMask(bool bAlpha) { - return m_pRenderer->GetAlphaMask(); + return m_pRenderer->CreateSoftMask(bAlpha); +} + +void CGraphicsRenderer::SetSoftMask(Aggplus::CSoftMask* pSoftMask) +{ + m_pRenderer->SetSoftMask(pSoftMask); } HRESULT CGraphicsRenderer::put_LayerOpacity(double dValue) @@ -1426,21 +1431,6 @@ HRESULT CGraphicsRenderer::put_LayerOpacity(double dValue) return m_pRenderer->SetLayerOpacity(dValue); } -HRESULT CGraphicsRenderer::put_LayerIsolated(bool bIsolated) -{ - return m_pRenderer->SetLayerIsolated(bIsolated); -} - -HRESULT CGraphicsRenderer::put_AlphaMaskIsolated(bool bIsolated) -{ - return m_pRenderer->SetAlphaMaskIsolated(bIsolated); -} - -void CGraphicsRenderer::put_AlphaMaskType(Aggplus::EMaskDataType oType) -{ - m_pRenderer->SetAlphaMaskType(oType); -} - 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 60a2c2cace..42fe58f573 100644 --- a/DesktopEditor/graphics/GraphicsRenderer.h +++ b/DesktopEditor/graphics/GraphicsRenderer.h @@ -348,18 +348,14 @@ public: inline double GetPixW() { return m_pRenderer->GetPixW(); } inline double GetPixH() { return m_pRenderer->GetPixH(); } - inline unsigned int GetLayerW() override { return m_pRenderer->GetLayerW(); } - inline unsigned int GetLayerH() override { return m_pRenderer->GetLayerH(); } // alpha mask methods void SetAlphaMask(Aggplus::CAlphaMask* pAlphaMask); - Aggplus::CAlphaMask* GetAlphaMask(); + virtual Aggplus::CSoftMask* CreateSoftMask(bool bAlpha) override; + virtual void SetSoftMask(Aggplus::CSoftMask* pSoftMask) override; // layer methods virtual HRESULT put_LayerOpacity(double dValue) override; - virtual HRESULT put_LayerIsolated(bool bIsolated) override; - virtual HRESULT put_AlphaMaskIsolated(bool bIsolated) override; - virtual void put_AlphaMaskType(Aggplus::EMaskDataType oType) override; // 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 7d03a7fbc4..d8273d734e 100644 --- a/DesktopEditor/graphics/IRenderer.h +++ b/DesktopEditor/graphics/IRenderer.h @@ -403,16 +403,6 @@ public: UNUSED_VARIABLE(dValue); return S_FALSE; } - virtual HRESULT put_LayerIsolated(bool bIsolated) - { - UNUSED_VARIABLE(bIsolated); - return S_FALSE; - } - virtual HRESULT put_AlphaMaskIsolated(bool bIsolated) - { - UNUSED_VARIABLE(bIsolated); - return S_FALSE; - } }; #define PROPERTY_RENDERER(NameBase, Name, Type) \ diff --git a/DesktopEditor/graphics/commands/AnnotField.cpp b/DesktopEditor/graphics/commands/AnnotField.cpp index fd8fe60ff5..84ceac5ed7 100644 --- a/DesktopEditor/graphics/commands/AnnotField.cpp +++ b/DesktopEditor/graphics/commands/AnnotField.cpp @@ -214,6 +214,11 @@ int CAnnotFieldInfo::GetID() const { return m_nID; } int CAnnotFieldInfo::GetAnnotFlag() const { return m_nAnnotFlag; } int CAnnotFieldInfo::GetPage() const { return m_nPage; } void CAnnotFieldInfo::GetBE(BYTE& nS, double& dI) { nS = m_pBE.first; dI = m_pBE.second; } +BYTE* CAnnotFieldInfo::GetRender(LONG& nLen) +{ + nLen = m_nRenderLen; + return m_pRender; +} const std::wstring& CAnnotFieldInfo::GetNM() { return m_wsNM; } const std::wstring& CAnnotFieldInfo::GetLM() { return m_wsLM; } const std::wstring& CAnnotFieldInfo::GetContents() { return m_wsContents; } @@ -337,6 +342,12 @@ bool CAnnotFieldInfo::Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, IMeta } if (nFlags & (1 << 5)) m_wsLM = pReader->ReadString(); + if (nFlags & (1 << 6)) + { + m_nRenderLen = pReader->ReadInt() - 4; + m_pRender = pReader->GetCurrentBuffer(); + pReader->Skip(m_nRenderLen); + } if (IsMarkup()) { @@ -567,11 +578,6 @@ const std::wstring& CAnnotFieldInfo::CFreeTextAnnotPr::GetDS() { return m_wsDS; void CAnnotFieldInfo::CFreeTextAnnotPr::GetRD(double& dRD1, double& dRD2, double& dRD3, double& dRD4) { dRD1 = m_dRD[0]; dRD2 = m_dRD[1]; dRD3 = m_dRD[2]; dRD4 = m_dRD[3]; } const std::vector& CAnnotFieldInfo::CFreeTextAnnotPr::GetCL() { return m_arrCL; } const std::vector& CAnnotFieldInfo::CFreeTextAnnotPr::GetIC() { return m_arrIC; } -BYTE* CAnnotFieldInfo::CFreeTextAnnotPr::GetRender(LONG& nLen) -{ - nLen = m_nRenderLen; - return m_pRender; -} void CAnnotFieldInfo::CFreeTextAnnotPr::Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, int nFlags) { m_nQ = pReader->ReadByte(); @@ -601,12 +607,6 @@ void CAnnotFieldInfo::CFreeTextAnnotPr::Read(NSOnlineOfficeBinToPdf::CBufferRead for (int i = 0; i < n; ++i) m_arrIC.push_back(pReader->ReadDouble()); } - if (nFlags & (1 << 22)) - { - m_nRenderLen = pReader->ReadInt() - 4; - m_pRender = pReader->GetCurrentBuffer(); - pReader->Skip(m_nRenderLen); - } } BYTE CAnnotFieldInfo::CCaretAnnotPr::GetSy() const { return m_nSy; } diff --git a/DesktopEditor/graphics/commands/AnnotField.h b/DesktopEditor/graphics/commands/AnnotField.h index 2f1e86fe94..5f53602dda 100644 --- a/DesktopEditor/graphics/commands/AnnotField.h +++ b/DesktopEditor/graphics/commands/AnnotField.h @@ -372,7 +372,6 @@ public: void GetRD(double& dRD1, double& dRD2, double& dRD3, double& dRD4); const std::vector& GetCL(); const std::vector& GetIC(); - BYTE* GetRender(LONG& nLen); void Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, int nFlags); @@ -385,8 +384,6 @@ public: double m_dRD[4]{}; std::vector m_arrCL; std::vector m_arrIC; - LONG m_nRenderLen; - BYTE* m_pRender; }; class GRAPHICS_DECL CCaretAnnotPr @@ -414,6 +411,7 @@ public: int GetAnnotFlag() const; int GetPage() const; void GetBE(BYTE& nS, double& dI); + BYTE* GetRender(LONG& nLen); const std::wstring& GetNM(); const std::wstring& GetLM(); const std::wstring& GetContents(); @@ -472,6 +470,8 @@ private: std::pair m_pBE; std::vector m_arrC; CBorder m_oBorder; + LONG m_nRenderLen; + BYTE* m_pRender; CMarkupAnnotPr* m_pMarkupPr; CTextAnnotPr* m_pTextPr; diff --git a/DesktopEditor/graphics/commands/DocInfo.cpp b/DesktopEditor/graphics/commands/DocInfo.cpp index 6abe8edd3d..d36f2c1a6d 100644 --- a/DesktopEditor/graphics/commands/DocInfo.cpp +++ b/DesktopEditor/graphics/commands/DocInfo.cpp @@ -164,24 +164,57 @@ bool CPageRotate::Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, IMetafile return true; } +CHeadings::CHeading::CHeading() +{ + nPage = 0; + dX = 0.0; + dY = 0.0; + pParent = NULL; +} +CHeadings::CHeading::~CHeading() +{ + for (int i = 0; i < arrHeading.size(); ++i) + RELEASEOBJECT(arrHeading[i]); +} + CHeadings::CHeadings() : IAdvancedCommand(AdvancedCommandType::Headings) {} -const std::vector& CHeadings::GetHeading() { return m_arrHeading; } +CHeadings::~CHeadings() +{ + for (int i = 0; i < m_arrHeading.size(); ++i) + RELEASEOBJECT(m_arrHeading[i]); +} +const std::vector& CHeadings::GetHeading() { return m_arrHeading; } bool CHeadings::Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, IMetafileToRenderter* pCorrector) { + int nPredLevel = 0, nHeaderLevel = 0; + std::vector* arrHeading = &m_arrHeading; + CHeading* pParent = NULL; int nHeadings = pReader->ReadInt(); for (int i = 0; i < nHeadings; ++i) - m_arrHeading.push_back(ReadHeading(pReader)); + { + int nLevel = pReader->ReadInt(); + if (nLevel > nPredLevel && i > 0) + { + nHeaderLevel = nPredLevel; + pParent = arrHeading->back(); + arrHeading = &pParent->arrHeading; + } + else if (nLevel < nPredLevel && nLevel <= nHeaderLevel) + { + nHeaderLevel = nLevel; + pParent = pParent ? pParent->pParent : NULL; + arrHeading = pParent ? &pParent->arrHeading : &m_arrHeading; + } + nPredLevel = nLevel; + + CHeading* pHeading = new CHeading(); + pHeading->nPage = pReader->ReadInt(); + pHeading->dX = pReader->ReadDouble(); + pHeading->dY = pReader->ReadDouble(); + pHeading->wsTitle = pReader->ReadString(); + pHeading->pParent = pParent; + + arrHeading->push_back(pHeading); + } return true; } -CHeadings::CHeading CHeadings::ReadHeading(NSOnlineOfficeBinToPdf::CBufferReader* pReader) -{ - CHeading oHeading; - oHeading.wsTitle = pReader->ReadString(); - oHeading.nPage = pReader->ReadInt(); - oHeading.dX = pReader->ReadDouble(); - oHeading.dY = pReader->ReadDouble(); - int nHeadings = pReader->ReadInt(); - for (int i = 0; i < nHeadings; ++i) - oHeading.arrHeading.push_back(ReadHeading(pReader)); - return oHeading; -} diff --git a/DesktopEditor/graphics/commands/DocInfo.h b/DesktopEditor/graphics/commands/DocInfo.h index 19c164e0ba..e0850188ff 100644 --- a/DesktopEditor/graphics/commands/DocInfo.h +++ b/DesktopEditor/graphics/commands/DocInfo.h @@ -179,19 +179,22 @@ public: int nPage; double dX; double dY; - std::vector arrHeading; + CHeading* pParent; + std::vector arrHeading; + + CHeading(); + ~CHeading(); }; CHeadings(); + ~CHeadings(); bool Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, IMetafileToRenderter* pCorrector); - const std::vector& GetHeading(); + const std::vector& GetHeading(); private: - std::vector m_arrHeading; - - CHeading ReadHeading(NSOnlineOfficeBinToPdf::CBufferReader* pReader); + std::vector m_arrHeading; }; diff --git a/DesktopEditor/graphics/pro/Graphics.h b/DesktopEditor/graphics/pro/Graphics.h index e1a143a1b3..d3ecf96a14 100644 --- a/DesktopEditor/graphics/pro/Graphics.h +++ b/DesktopEditor/graphics/pro/Graphics.h @@ -117,13 +117,11 @@ namespace NSGraphics virtual void Stroke() = 0; virtual double GetPixW() = 0; virtual double GetPixH() = 0; - virtual unsigned int GetLayerW() = 0; - virtual unsigned int GetLayerH() = 0; //alpha mask methods virtual void SetAlphaMask(Aggplus::CAlphaMask* pAlphaMask) = 0; - virtual Aggplus::CAlphaMask* GetAlphaMask() = 0; - virtual void put_AlphaMaskType(Aggplus::EMaskDataType oType) = 0; + virtual Aggplus::CSoftMask* CreateSoftMask(bool bAlpha) = 0; + virtual void SetSoftMask(Aggplus::CSoftMask* pSoftMask) = 0; // smart methods virtual void drawHorLine(BYTE align, double y, double x, double r, double penW) = 0; diff --git a/DesktopEditor/graphics/pro/js/drawingfile.json b/DesktopEditor/graphics/pro/js/drawingfile.json index 1a5e6af811..bb38a4493c 100644 --- a/DesktopEditor/graphics/pro/js/drawingfile.json +++ b/DesktopEditor/graphics/pro/js/drawingfile.json @@ -222,7 +222,7 @@ }, { "folder": "../../../../DocxRenderer/src/logic/elements", - "files": ["BaseItem.cpp", "ContText.cpp", "DropCap.cpp", "Image.cpp", "Paragraph.cpp", "Shape.cpp", "TextLine.cpp"] + "files": ["BaseItem.cpp", "ContText.cpp", "DropCap.cpp", "Paragraph.cpp", "Shape.cpp", "TextLine.cpp"] }, { "folder": "../../../common", diff --git a/DesktopEditor/graphics/shading_info.h b/DesktopEditor/graphics/shading_info.h index 4ea5cc9b23..c97c08f806 100644 --- a/DesktopEditor/graphics/shading_info.h +++ b/DesktopEditor/graphics/shading_info.h @@ -468,14 +468,14 @@ namespace NSStructures { GradientInfo ginfo; ginfo.shading.triangle = points; + ginfo.shading.shading_type = ShadingInfo::Parametric; + ginfo.shading.function = ColorFunction(256, t0, t1); + ginfo.continue_shading_f = false; + ginfo.continue_shading_b = false; if (parametric) { ginfo.shading.triangle_parameters = params; - ginfo.shading.f_type = ShadingInfo::UseNew; - ginfo.shading.function = ColorFunction(256, t0, t1); ginfo.shading.shading_type = ShadingInfo::Parametric; - ginfo.continue_shading_f = false; - ginfo.continue_shading_b = false; } else { @@ -513,7 +513,10 @@ namespace NSStructures ginfo.shading.patch[2][0] = curve_points[10]; ginfo.shading.patch[1][0] = curve_points[11]; - + ginfo.shading.f_type = ShadingInfo::UseNew; + ginfo.shading.function = ColorFunction(256, t0, t1); + ginfo.continue_shading_f = false; + ginfo.continue_shading_b = false; if (parametric) { @@ -522,11 +525,7 @@ namespace NSStructures ginfo.shading.patch_parameters[0][1] = curve_parametrs[1]; ginfo.shading.patch_parameters[1][0] = curve_parametrs[3]; ginfo.shading.patch_parameters[1][1] = curve_parametrs[2]; - ginfo.shading.f_type = ShadingInfo::UseNew; - ginfo.shading.function = ColorFunction(256, t0, t1); ginfo.shading.shading_type = ShadingInfo::Parametric; - ginfo.continue_shading_f = false; - ginfo.continue_shading_b = false; } else { @@ -549,14 +548,15 @@ namespace NSStructures ginfo.shading.patch = curve_poits; + ginfo.shading.f_type = ShadingInfo::UseNew; + ginfo.shading.function = ColorFunction(256, t0, t1); + ginfo.continue_shading_f = false; + ginfo.continue_shading_b = false; + if (parametric) { ginfo.shading.patch_parameters = curve_parametrs; - ginfo.shading.f_type = ShadingInfo::UseNew; - ginfo.shading.function = ColorFunction(256, t0, t1); ginfo.shading.shading_type = ShadingInfo::Parametric; - ginfo.continue_shading_f = false; - ginfo.continue_shading_b = false; } else { diff --git a/DocxRenderer/DocxRenderer.cpp b/DocxRenderer/DocxRenderer.cpp index b1f7243f99..e6aa677506 100644 --- a/DocxRenderer/DocxRenderer.cpp +++ b/DocxRenderer/DocxRenderer.cpp @@ -78,15 +78,24 @@ HRESULT CDocxRenderer::SetTextAssociationType(const NSDocxRenderer::TextAssociat return S_OK; } -int CDocxRenderer::Convert(IOfficeDrawingFile* pFile, const std::wstring& sDstFile, bool bIsOutCompress) +int CDocxRenderer::Convert(IOfficeDrawingFile* pFile, const std::wstring& sDst, bool bIsOutCompress) { #ifndef DISABLE_FULL_DOCUMENT_CREATION - m_pInternal->m_oDocument.m_strDstFilePath = sDstFile; + m_pInternal->m_oDocument.m_strDstFilePath = sDst; + + m_pInternal->m_oDocument.m_oCurrentPage.m_bUseDefaultFont = false; + m_pInternal->m_oDocument.m_oCurrentPage.m_bWriteStyleRaw = false; if (bIsOutCompress) m_pInternal->m_oDocument.m_strTempDirectory = NSDirectory::CreateDirectoryWithUniqueName(m_pInternal->m_sTempDirectory); else - m_pInternal->m_oDocument.m_strTempDirectory= m_pInternal->m_sTempDirectory; + { + if (NSDirectory::Exists(sDst)) + NSDirectory::DeleteDirectory(sDst); + + NSDirectory::CreateDirectories(sDst); + m_pInternal->m_oDocument.m_strTempDirectory = sDst; + } m_pInternal->m_oDocument.Init(); m_pInternal->m_oDocument.CreateTemplates(); diff --git a/DocxRenderer/DocxRenderer.pro b/DocxRenderer/DocxRenderer.pro index a1c6860787..eeb2f30eec 100644 --- a/DocxRenderer/DocxRenderer.pro +++ b/DocxRenderer/DocxRenderer.pro @@ -31,7 +31,6 @@ HEADERS += \ src/logic/elements/BaseItem.h \ src/logic/elements/ContText.h \ src/logic/elements/DropCap.h \ - src/logic/elements/Image.h \ src/logic/elements/Paragraph.h \ src/logic/elements/Shape.h \ src/logic/elements/TextLine.h \ @@ -56,7 +55,6 @@ SOURCES += \ src/logic/elements/BaseItem.cpp \ src/logic/elements/ContText.cpp \ src/logic/elements/DropCap.cpp \ - src/logic/elements/Image.cpp \ src/logic/elements/Paragraph.cpp \ src/logic/elements/Shape.cpp \ src/logic/elements/TextLine.cpp \ diff --git a/DocxRenderer/src/logic/Document.cpp b/DocxRenderer/src/logic/Document.cpp index 36e2aed13e..7472ae79fc 100644 --- a/DocxRenderer/src/logic/Document.cpp +++ b/DocxRenderer/src/logic/Document.cpp @@ -7,7 +7,7 @@ namespace NSDocxRenderer { CDocument::CDocument(IRenderer* pRenderer, NSFonts::IApplicationFonts* pFonts) : - m_pAppFonts(pFonts), m_oCurrentPage(pFonts), m_oFontManager(pFonts), m_oFontSelector(pFonts) + m_pAppFonts(pFonts), m_oCurrentPage(), m_oFontManager(pFonts), m_oFontSelector(pFonts) { m_oSimpleGraphicsConverter.SetRenderer(pRenderer); } @@ -628,19 +628,14 @@ namespace NSDocxRenderer HRESULT CDocument::DrawPath(long nType) { std::shared_ptr pInfo = nullptr; - if ((nType > 0xFF) && (c_BrushTypeTexture == m_oBrush.Type)) { - double x = 0; - double y = 0; - double w = 0; - double h = 0; + double x = 0, y = 0, w = 0, h = 0; if (m_oBrush.Image) pInfo = m_oImageManager.WriteImage(m_oBrush.Image, x, y, w, h); else pInfo = m_oImageManager.WriteImage(m_oBrush.TexturePath, x, y, w, h); } - m_oCurrentPage.DrawPath(nType, pInfo); return S_OK; } @@ -817,16 +812,16 @@ namespace NSDocxRenderer m_lCurrentCommandType = 0; m_oCurrentPage.Init(&m_oFont, - &m_oPen, - &m_oBrush, - &m_oShadow, - &m_oEdge, - &m_oTransform, - &m_oSimpleGraphicsConverter, - &m_oFontStyleManager, - &m_oFontManager, - &m_oFontSelector, - &m_oParagraphStyleManager); + &m_oPen, + &m_oBrush, + &m_oShadow, + &m_oEdge, + &m_oTransform, + &m_oSimpleGraphicsConverter, + &m_oFontStyleManager, + &m_oFontManager, + &m_oFontSelector, + &m_oParagraphStyleManager); m_oImageManager.Clear(); m_oFontStyleManager.Clear(); diff --git a/DocxRenderer/src/logic/Page.cpp b/DocxRenderer/src/logic/Page.cpp index 5c770a4ef8..fe56263135 100644 --- a/DocxRenderer/src/logic/Page.cpp +++ b/DocxRenderer/src/logic/Page.cpp @@ -6,21 +6,21 @@ namespace NSDocxRenderer { - CPage::CPage(NSFonts::IApplicationFonts* pFonts) + CPage::CPage() { } void CPage::Init(NSStructures::CFont* pFont, - NSStructures::CPen* pPen, - NSStructures::CBrush* pBrush, - NSStructures::CShadow* pShadow, - NSStructures::CEdgeText* pEdge, - Aggplus::CMatrix* pMatrix, - Aggplus::CGraphicsPathSimpleConverter* pSimple, - CFontStyleManager* pFontStyleManager, - CFontManager *pFontManager, - CFontSelector* pFontSelector, - CParagraphStyleManager* pParagraphStyleManager) + NSStructures::CPen* pPen, + NSStructures::CBrush* pBrush, + NSStructures::CShadow* pShadow, + NSStructures::CEdgeText* pEdge, + Aggplus::CMatrix* pMatrix, + Aggplus::CGraphicsPathSimpleConverter* pSimple, + CFontStyleManager* pFontStyleManager, + CFontManager *pFontManager, + CFontSelector* pFontSelector, + CParagraphStyleManager* pParagraphStyleManager) { m_pFont = pFont; m_pPen = pPen; @@ -36,8 +36,6 @@ namespace NSDocxRenderer m_pFontSelector = pFontSelector; m_pParagraphStyleManager = pParagraphStyleManager; - m_pCurrentLine = nullptr; - CShape::ResetRelativeHeight(); } @@ -55,10 +53,7 @@ namespace NSDocxRenderer m_arImages.clear(); m_arShapes.clear(); m_arOutputObjects.clear(); - - m_pCurrentLine = nullptr; m_oVector.Clear(); - m_arCompleteObjectsXml.clear(); } @@ -78,91 +73,44 @@ namespace NSDocxRenderer // image commands void CPage::WriteImage(const std::shared_ptr pInfo, double& fX, double& fY, double& fWidth, double& fHeight) { - auto pImage = std::make_shared(pInfo, L""); - pImage->m_eType = CShape::eShapeType::stPicture; + auto image = std::make_shared(pInfo, L""); + image->m_eType = CShape::eShapeType::stPicture; - double dRotation = m_pTransform->z_Rotation(); + double rotation = m_pTransform->z_Rotation(); - if (fabs(dRotation) < 5.0) - { - double x1 = fX; - double y1 = fY; - double x2 = fX + fWidth; - double y2 = fY + fHeight; + Point p1(fX, fY); + Point p2(fX + fWidth, fY + fHeight); - m_pTransform->TransformPoint(x1, y1); - m_pTransform->TransformPoint(x2, y2); + m_pTransform->TransformPoint(p1.x, p1.y); + m_pTransform->TransformPoint(p2.x, p2.y); - if (x1 <= x2) - { - pImage->m_dLeft = x1; - pImage->m_dWidth = x2 - x1; - } - else - { - pImage->m_dLeft = x2; - pImage->m_dWidth = x1 - x2; - } + // rotate - calc all 4 points - rotate it back + Point c((p1.x + p2.x) / 2, (p1.y + p2.y) / 2); + Aggplus::CMatrix rotate_matrix; + rotate_matrix.RotateAt(-rotation, c.x, c.y, Aggplus::MatrixOrderAppend); - if (y1 <= y2) - { - pImage->m_dTop = y1; - pImage->m_dHeight = y2 - y1; - } - else - { - pImage->m_dTop = y2; - pImage->m_dHeight = y1 - y2; - } + rotate_matrix.TransformPoint(p1.x, p1.y); + rotate_matrix.TransformPoint(p2.x, p2.y); - pImage->m_dRotate = 0.0; - } - else - { - double x1 = fX; - double y1 = fY; - double x2 = fX + fWidth; - double y2 = fY + fHeight; + Point p3(p1.x, p2.y); + Point p4(p2.x, p1.y); - Aggplus::CMatrix oTemp = *m_pTransform; + image->m_dBaselinePos = std::max({p1.y, p2.y, p3.y, p4.y}); + image->m_dTop = std::min({p1.y, p2.y, p3.y, p4.y}); + image->m_dLeft = std::min({p1.x, p2.x, p3.x, p4.x}); + image->m_dRight = std::max({p1.x, p2.x, p3.x, p4.x}); - double dCx = (x1 + x2) / 2; - double dCy = (y1 + y2) / 2; - m_pTransform->TransformPoint(dCx, dCy); - oTemp.RotateAt(-dRotation, dCx, dCy, Aggplus::MatrixOrderAppend); + image->m_dHeight = image->m_dBaselinePos - image->m_dTop; + image->m_dWidth = image->m_dRight - image->m_dLeft; + image->m_dRotate = rotation; - oTemp.TransformPoint(x1, y1); - oTemp.TransformPoint(x2, y2); +// rotate_matrix.RotateAt(rotation, c.x, c.y, Aggplus::MatrixOrderAppend); +// rotate_matrix.TransformPoint(p1.x, p1.y); +// rotate_matrix.TransformPoint(p2.x, p2.y); +// rotate_matrix.TransformPoint(p3.x, p3.y); +// rotate_matrix.TransformPoint(p4.x, p4.y); - if (x1 <= x2) - { - pImage->m_dLeft = x1; - pImage->m_dWidth = x2 - x1; - } - else - { - pImage->m_dLeft = x2; - pImage->m_dWidth = x1 - x2; - } - - if (y1 <= y2) - { - pImage->m_dTop = y1; - pImage->m_dHeight = y2 - y1; - } - else - { - pImage->m_dTop = y2; - pImage->m_dHeight = y1 - y2; - } - - pImage->m_dRotate = dRotation; - } - - pImage->m_dBaselinePos = pImage->m_dTop + pImage->m_dHeight; - pImage->m_dRight = pImage->m_dLeft + pImage->m_dWidth; - - m_arImages.push_back(pImage); + m_arImages.push_back(image); } // path commands @@ -270,25 +218,30 @@ namespace NSDocxRenderer pShape->m_oPen.Size *= dDeterminant; pShape->SetVector(std::move(m_oVector)); + + // big white shape with page width & height skip + if (fabs(pShape->m_dHeight - m_dHeight) <= c_dSHAPE_X_OFFSET * 2 && + fabs(pShape->m_dWidth - m_dWidth) <= c_dSHAPE_X_OFFSET * 2 && + pShape->m_oBrush.Color1 == c_iWhiteColor) + return; + + pShape->m_nOrder = ++m_nShapeOrder; m_arShapes.push_back(pShape); } } void CPage::CollectTextData(const PUINT pUnicodes, - const PUINT pGids, - const UINT& nCount, - const double& fX, - const double& fY, - const double& fWidth, - const double& fHeight, - const double& fBaseLineOffset) + const PUINT pGids, + const UINT& nCount, + const double& fX, + const double& fY, + const double& fWidth, + const double& fHeight, + const double& fBaseLineOffset) { // 9 - \t - if (pUnicodes != nullptr && nCount == 1 && (IsSpaceUtf32(*pUnicodes) || *pUnicodes == 9)) - { - //note пробелы не нужны, добавляются при анализе + if (*pUnicodes == 9) return; - } double dTextX = fX; double dTextY = fY; @@ -306,14 +259,13 @@ namespace NSDocxRenderer oText[i] = ' '; // иногда приходит неверный? размер, нужно перемерить (XPS) - if(m_bIsRecalcFontSize) + if (m_bIsRecalcFontSize) { m_pFont->Size *= ((m_pTransform->sx() + m_pTransform->sy()) / 2); m_bIsRecalcFontSize = false; } m_pFontManager->LoadFontByFile(*m_pFont); - // закомментив это, все гуд //if (fabs(dTextW) < 0.01 || (dTextW > 10)) //{ @@ -335,11 +287,70 @@ namespace NSDocxRenderer } //} - double dBaseLinePos = dTextY + fBaseLineOffset; + auto oMetrics = m_pFontManager->GetFontMetrics(); + _h = m_pFontManager->GetFontHeight(); + + double baseline = dTextY + fBaseLineOffset; + double top = baseline - _h; + double height = baseline - top; + double left = dTextX; + double width = _w; + double right = left + _w; + + // if new text is close to current cont + if (m_pCurrCont != nullptr && + fabs(m_pCurrCont->m_dBaselinePos - baseline) < c_dTHE_SAME_STRING_Y_PRECISION_MM && + m_oPrevFont.IsEqual2(m_pFont) && + m_oPrevBrush.IsEqual(m_pBrush)) + { + + double avg_width = width / oText.length(); + for (size_t i = 0; i < oText.length(); ++i) + if (oText.at(i) == c_SPACE_SYM) + m_pCurrCont->m_pFontStyle->UpdateAvgSpaceWidth(avg_width); + + double avg_space_width = m_pCurrCont->m_pFontStyle->GetAvgSpaceWidth(); + double space_width = avg_space_width != 0.0 ? + avg_space_width * c_dAVERAGE_SPACE_WIDTH_COEF : + m_pCurrCont->CalculateSpace() * c_dSPACE_WIDTH_COEF; + + bool is_added = false; + + // some_text+more_text + if (fabs(m_pCurrCont->m_dRight - left) < space_width && right > m_pCurrCont->m_dRight) + { + double left_avg_width = (right - m_pCurrCont->m_dRight) / oText.length(); + std::vector ar_widths; + for (size_t i = 0; i < oText.length(); ++i) + ar_widths.push_back(left_avg_width); + + m_pCurrCont->AddTextBack(oText, ar_widths); + is_added = true; + + } + // more_text+some_text + else if (fabs(m_pCurrCont->m_dLeft - right) < space_width && left < m_pCurrCont->m_dLeft) + { + double right_avg_width = (m_pCurrCont->m_dLeft - left) / oText.length(); + std::vector ar_widths; + for (size_t i = 0; i < oText.length(); ++i) + ar_widths.push_back(right_avg_width); + + m_pCurrCont->AddTextFront(oText, ar_widths); + is_added = true; + } + + if (is_added) + { + m_pCurrCont->m_dTop = std::min(m_pCurrCont->m_dTop, top); + m_pCurrCont->m_dBaselinePos = std::max(m_pCurrCont->m_dBaselinePos, baseline); + m_pCurrCont->m_dHeight = m_pCurrCont->m_dBaselinePos - m_pCurrCont->m_dTop; + m_pCurrCont->m_dWidth = m_pCurrCont->m_dRight - m_pCurrCont->m_dLeft; + return; + } + } auto pCont = std::make_shared(m_pFontManager); - - auto oMetrics = m_pFontManager->GetFontMetrics(); auto oParams = m_pFontManager->GetFontSelectParams(); // use forced fold option @@ -348,17 +359,33 @@ namespace NSDocxRenderer bForcedBold = true; m_pFontSelector->SelectFont(oParams, oMetrics, oText); - _h = m_pFontManager->GetFontHeight(); - pCont->m_dBaselinePos = dBaseLinePos; - pCont->m_dTop = pCont->m_dBaselinePos - _h; - pCont->m_dHeight = pCont->m_dBaselinePos - pCont->m_dTop; + pCont->m_dBaselinePos = baseline; + pCont->m_dTop = top; + pCont->m_dHeight = height; + pCont->m_dLeft = left; - pCont->m_dLeft = dTextX; - pCont->m_dWidth = _w; - pCont->m_dRight = dTextX + _w; + // первичное получение стиля для текущего символа + // при дальнейшем анализе может измениться + pCont->m_pFontStyle = m_pFontStyleManager->GetOrAddFontStyle(*m_pBrush, + m_pFontSelector->GetSelectedName(), + m_pFont->Size, + m_pFontSelector->IsSelectedItalic(), + m_pFontSelector->IsSelectedBold() || bForcedBold); - pCont->m_oText = oText; + // just in case if oText contains more than 1 symbol + std::vector ar_widths; + double avg_width = abs(right - left) / oText.length(); + for (size_t i = 0; i < oText.length(); ++i) + { + if (oText.at(i) == c_SPACE_SYM) pCont->m_pFontStyle->UpdateAvgSpaceWidth(avg_width); + ar_widths.push_back(avg_width); + } + + pCont->SetText(oText, ar_widths); + + pCont->m_dWidth = width; + pCont->m_dRight = right; double font_size = m_pFont->Size; double em_height = oMetrics.dEmHeight; @@ -366,15 +393,6 @@ namespace NSDocxRenderer pCont->m_dTopWithAscent = pCont->m_dBaselinePos - (oMetrics.dAscent * ratio) - oMetrics.dBaselineOffset; pCont->m_dBotWithDescent = pCont->m_dBaselinePos + (oMetrics.dDescent * ratio) - oMetrics.dBaselineOffset; - - // первичное получение стиля для текущего символа - // при дальнейшем анализе может измениться - pCont->m_pFontStyle = m_pFontStyleManager->GetOrAddFontStyle(*m_pBrush, - m_pFontSelector->GetSelectedName(), - m_pFont->Size, - m_pFontSelector->IsSelectedItalic(), - m_pFontSelector->IsSelectedBold() || bForcedBold); - pCont->m_dSpaceWidthMM = m_pFontManager->GetSpaceWidthMM(); if (m_bUseDefaultFont) @@ -393,64 +411,35 @@ namespace NSDocxRenderer pCont->m_bWriteStyleRaw = m_bWriteStyleRaw; m_pParagraphStyleManager->UpdateAvgFontSize(m_pFont->Size); m_arConts.push_back(pCont); - } - void CPage::AddContToTextLine(std::shared_ptr pCont) - { - if (nullptr == m_pCurrentLine) - { - auto pLine = std::make_shared(); - m_pCurrentLine = pLine.get(); - m_pCurrentLine->AddCont(pCont); - m_arTextLines.push_back(pLine); - return; - } - - if (fabs(m_pCurrentLine->m_dBaselinePos - pCont->m_dBaselinePos) <= c_dTHE_SAME_STRING_Y_PRECISION_MM) - { - m_pCurrentLine->AddCont(pCont); - return; - } - - for (size_t i = 0; i < m_arTextLines.size(); ++i) - { - if (fabs(m_arTextLines[i]->m_dBaselinePos - pCont->m_dBaselinePos) <= c_dTHE_SAME_STRING_Y_PRECISION_MM) - { - m_pCurrentLine = m_arTextLines[i].get(); - m_pCurrentLine->AddCont(pCont); - return; - } - } - - auto pLine = std::make_shared(); - m_pCurrentLine = pLine.get(); - m_pCurrentLine->AddCont(pCont); - m_arTextLines.push_back(pLine); + m_pCurrCont = pCont; + m_oPrevFont = *m_pFont; + m_oPrevBrush = *m_pBrush; } void CPage::Analyze() { + // analyze shapes (get type of lines etc) + AnalyzeShapes(); + // build m_arDiacriticalSymbols BuildDiacriticalSymbols(); // build text lines from m_arConts BuildTextLines(); - // analyze shapes (get type of lines etc) - AnalyzeShapes(); - // analyze text lines and conts inside AnalyzeTextLines(); // merge conts in text lines - BuildLines(); - - // calc sizes on selected fonts for m_arConts - CalcSelected(); + MergeConts(); // build paragraphs from m_arTextLines BuildParagraphes(); + // calc sizes on selected fonts for m_arConts + CalcSelected(); + // merge shapes MergeShapes(); } @@ -464,26 +453,64 @@ namespace NSDocxRenderer void CPage::BuildDiacriticalSymbols() { for (size_t i = 0; i < m_arConts.size(); i++) - if (m_arConts[i] && m_arConts[i]->m_oText.length() == 1 && IsDiacriticalMark(m_arConts[i]->m_oText[0])) - m_arDiacriticalSymbols.push_back(std::move(m_arConts[i])); - + { + if (m_arConts[i] && m_arConts[i]->GetText().length() == 1) + { + const auto& text = m_arConts[i]->GetText(); + if (IsDiacriticalMark(text.at(0))) + m_arDiacriticalSymbols.push_back(std::move(m_arConts[i])); + } + } } + void CPage::BuildTextLines() { - using cont_ptr_t = std::shared_ptr; - std::sort(m_arConts.begin(), m_arConts.end(), [] (const cont_ptr_t& a, const cont_ptr_t& b) { - if(!a) return false; - if(!b) return true; - - if (fabs(a->m_dBaselinePos - b->m_dBaselinePos) <= c_dTHE_SAME_STRING_Y_PRECISION_MM) - return a->m_dLeft < b->m_dLeft; - - return a->m_dBaselinePos < b->m_dBaselinePos; - }); - + std::shared_ptr curr_line = nullptr; for (auto& cont : m_arConts) - if (cont) - AddContToTextLine(cont); + { + if (!cont) + continue; + + if (curr_line && fabs(curr_line->m_dBaselinePos - cont->m_dBaselinePos) <= c_dTHE_SAME_STRING_Y_PRECISION_MM) + { + curr_line->AddCont(cont); + continue; + } + + bool skip = false; + for (size_t i = 0; i < m_arTextLines.size(); ++i) + { + if (fabs(m_arTextLines[i]->m_dBaselinePos - cont->m_dBaselinePos) <= c_dTHE_SAME_STRING_Y_PRECISION_MM) + { + curr_line = m_arTextLines[i]; + cont->m_bPossibleSplit = true; + curr_line->AddCont(cont); + skip = true; + } + } + + if (skip) + continue; + + curr_line = std::make_shared(); + curr_line->AddCont(cont); + m_arTextLines.push_back(curr_line); + } + + for (size_t i = 0; i < m_arTextLines.size(); i++) + { + bool only_spaces = true; + for (auto& cont : m_arTextLines[i]->m_arConts) + { + if (!cont->IsOnlySpaces()) + { + only_spaces = false; + break; + } + } + if (only_spaces) + m_arTextLines.erase(m_arTextLines.begin() + i, m_arTextLines.begin() + i + 1); + } } void CPage::MergeShapes() @@ -491,13 +518,20 @@ namespace NSDocxRenderer if (m_arShapes.empty()) return; + using shape_ptr_t = std::shared_ptr; + std::sort(m_arShapes.begin(), m_arShapes.end(), [] (const shape_ptr_t& a, const shape_ptr_t& b) { + if (!a) return false; + if (!b) return true; + return a->m_nOrder < b->m_nOrder; + }); + using shape_ref_ptr_t = std::reference_wrapper>; for (size_t i = 0; i < m_arShapes.size() - 1; i++) { shape_ref_ptr_t val = m_arShapes[i]; shape_ref_ptr_t next_val = m_arShapes[i + 1]; - if(!val.get() || ! next_val.get()) + if (!val.get() || ! next_val.get()) continue; next_val.get()->TryMergeShape(val.get()); @@ -506,26 +540,26 @@ namespace NSDocxRenderer void CPage::CalcSelected() { - for (auto& cont : m_arConts) - { - if (cont && cont->m_oSelectedSizes.dHeight == 0.0 && cont->m_oSelectedSizes.dWidth == 0.0) + for (auto& line : m_arTextLines) + for (auto& cont : line->m_arConts) { - if (m_bUseDefaultFont) + if (cont && cont->m_oSelectedSizes.dHeight == 0.0 && cont->m_oSelectedSizes.dWidth == 0.0) { - cont->m_oSelectedSizes.dHeight = cont->m_dHeight; - cont->m_oSelectedSizes.dWidth = cont->m_dWidth; - } - else - { - cont->CalcSelected(); + if (m_bUseDefaultFont) + { + cont->m_oSelectedSizes.dHeight = cont->m_dHeight; + cont->m_oSelectedSizes.dWidth = cont->m_dWidth; + } + else + { + cont->CalcSelected(); + } } } - } } void CPage::AnalyzeShapes() { - //BuildTables(); DetermineLinesType(); } @@ -539,8 +573,8 @@ namespace NSDocxRenderer for (size_t i = 0; i < m_arShapes.size(); ++i) { if (!m_arShapes[i] || m_arShapes[i]->m_dHeight > c_dMAX_LINE_HEIGHT_MM || // рассматриваем только тонкие объекты - (m_arShapes[i]->m_eGraphicsType != eGraphicsType::gtRectangle && - m_arShapes[i]->m_eGraphicsType != eGraphicsType::gtCurve)) + (m_arShapes[i]->m_eGraphicsType != eGraphicsType::gtRectangle && + m_arShapes[i]->m_eGraphicsType != eGraphicsType::gtCurve)) { continue; } @@ -606,8 +640,8 @@ namespace NSDocxRenderer // analyze conts in text lines AnalyzeConts(); - // assign highlights to conts & delete shapes which is uses in highlights - DetermineStrikeoutsUnderlinesHighlights(); + // Strikeout, underline, outline, highlight + AnalyzeEffects(); // diacritical symbols AddDiacriticalSymbols(); @@ -630,7 +664,7 @@ namespace NSDocxRenderer { auto& line = m_arTextLines[i]; for (auto& cont : line->m_arConts) - if (cont && cont->m_pFontStyle->dFontSize > 2 * avg_font_size && cont->m_oText.length() == 1) + if (cont && cont->m_pFontStyle->dFontSize > 2 * avg_font_size && cont->GetText().length() == 1) possible_caps.push_back({cont, line}); } @@ -671,7 +705,7 @@ namespace NSDocxRenderer *static_cast(drop_cap.get()) = *drop_cap_cont; drop_cap->nLines = num_of_lines; drop_cap->wsFont = drop_cap_cont->m_pFontStyle->wsFontName; - drop_cap->wsText = drop_cap_cont->m_oText.ToStdWString(); + drop_cap->wsText = drop_cap_cont->GetText().ToStdWString(); drop_cap->nFontSize = static_cast(drop_cap_cont->m_pFontStyle->dFontSize * 2); drop_caps.push_back(std::move(drop_cap)); @@ -753,7 +787,7 @@ namespace NSDocxRenderer eHorizontalCrossingType eHType = pCurrCont->GetHorizontalCrossingType(pNextCont.get()); bool is_font_effect = CContText::CheckFontEffects(pCurrCont, pNextCont, eVType, eHType); - if(!is_font_effect && CContText::CheckVertAlignTypeBetweenConts(pCurrCont, pNextCont, eVType, eHType)) + if (!is_font_effect && CContText::CheckVertAlignTypeBetweenConts(pCurrCont, pNextCont, eVType, eHType)) { pCurrLine->SetVertAlignType(pCurrCont->m_eVertAlignType); pNextLine->SetVertAlignType(pNextCont->m_eVertAlignType); @@ -766,24 +800,23 @@ namespace NSDocxRenderer pNextLine->m_pLine = pCurrLine; } } - else if(!is_font_effect && pCurrCont->IsDuplicate(pNextCont.get(), eVType)) + else if (!is_font_effect && pCurrCont->IsDuplicate(pNextCont.get(), eVType)) { pNextCont = nullptr; pCurrCont->m_iNumDuplicates++; } } - if(pNextLine && pNextLine->IsCanBeDeleted()) + if (pNextLine && pNextLine->IsCanBeDeleted()) pNextLine = nullptr; } } - if(pCurrLine && pCurrLine->IsCanBeDeleted()) + if (pCurrLine && pCurrLine->IsCanBeDeleted()) pCurrLine = nullptr; } } - void CPage::DetermineStrikeoutsUnderlinesHighlights() + void CPage::AnalyzeEffects() { - // определение различных эффектов на основании взаимного расположения символов и шейпов for (size_t i = 0; i < m_arShapes.size(); ++i) { auto& shape = m_arShapes[i]; @@ -791,97 +824,105 @@ namespace NSDocxRenderer continue; bool shape_used = false; - for (size_t j = 0; j < m_arTextLines.size(); ++j) { - auto& pCurrLine = m_arTextLines[j]; - if (!pCurrLine || (pCurrLine->AreObjectsNoCrossingByVertically(shape.get()) && - (pCurrLine->m_dTop > shape->m_dBaselinePos || - pCurrLine->m_dBaselinePos + pCurrLine->m_dHeight < shape->m_dTop))) - { + auto& curr_line = m_arTextLines[j]; + if (!curr_line) continue; - } - for (size_t k = 0; k < pCurrLine->m_arConts.size(); ++k) + bool is_no_crossing_v = curr_line->AreObjectsNoCrossingByVertically(shape.get()); + bool is_higher = curr_line->m_dTop > shape->m_dBaselinePos; + bool is_lower = curr_line->m_dBaselinePos + curr_line->m_dHeight < shape->m_dTop; + if (is_no_crossing_v && (is_higher || is_lower)) + continue; + + for (size_t k = 0; k < curr_line->m_arConts.size(); ++k) { - if(!shape) - break; - - auto& curr_cont = pCurrLine->m_arConts[k]; + std::shared_ptr curr_cont = curr_line->m_arConts[k]; if (!curr_cont) continue; - eVerticalCrossingType eVType = curr_cont->CBaseItem::GetVerticalCrossingType(shape.get()); - eHorizontalCrossingType eHType = curr_cont->GetHorizontalCrossingType(shape.get()); + bool is_width_equal = (curr_line->m_dWidth * 1.05 - shape->m_dWidth) > 0; - bool bIsNotComplicatedFigure = shape->m_eGraphicsType != eGraphicsType::gtComplicatedFigure; - bool bIsLineCrossingText = IsLineCrossingText(shape.get(), curr_cont.get(), eHType); - bool bIsItHighlightingBackground = IsItHighlightingBackground(shape.get(), curr_cont.get(), eHType); - bool bIsLineBelowText = IsLineBelowText(shape.get(), curr_cont.get(), eHType); + bool is_crossing_text = IsLineCrossingText(shape, curr_cont) && is_width_equal; + bool is_below_text = IsLineBelowText(shape, curr_cont) && is_width_equal; + bool is_outline = IsOutline(shape, curr_cont); + bool is_highlight = IsHighlight(shape, curr_cont) && curr_line->m_dHeight * 1.5 > shape->m_dHeight && is_width_equal; - if (bIsLineCrossingText) + bool is_smth_true = is_crossing_text || is_below_text || is_outline || is_highlight; + if (is_smth_true) { - curr_cont->m_bIsStrikeoutPresent = true; - if (shape->m_eLineType == eLineType::ltDouble) - curr_cont->m_bIsDoubleStrikeout = true; - } + // if crossing a part of cont - split it + if (shape->m_dLeft > curr_cont->m_dLeft) + { + auto another_cont = curr_cont->Split(shape->m_dLeft); + if (another_cont != nullptr) + { + curr_line->m_arConts.insert(curr_line->m_arConts.begin() + k, another_cont); + ++k; + curr_cont = another_cont; + } + } + if (shape->m_dRight < curr_cont->m_dRight) + { + auto another_cont = curr_cont->Split(shape->m_dRight); + if (another_cont != nullptr) + { + curr_line->m_arConts.insert(curr_line->m_arConts.begin() + k + 1, another_cont); + ++k; + } + } - else if (bIsItHighlightingBackground) - { - //Удовлетворяет расположением и размером - привязываем указатель на картинку - curr_cont->m_pShape = shape; - curr_cont->m_bIsHighlightPresent = true; - curr_cont->m_lHighlightColor = shape->m_oBrush.Color1; - } + if (is_crossing_text) + { + curr_cont->m_bIsStrikeoutPresent = true; + if (shape->m_eLineType == eLineType::ltDouble) + curr_cont->m_bIsDoubleStrikeout = true; + } - else if (bIsLineBelowText) - { - curr_cont->m_bIsUnderlinePresent = true; - curr_cont->m_eUnderlineType = shape->m_eLineType; - curr_cont->m_lUnderlineColor = shape->m_dHeight > 0.3 ? shape->m_oBrush.Color1 : shape->m_oPen.Color; + else if (is_below_text) + { + curr_cont->m_bIsUnderlinePresent = true; + curr_cont->m_eUnderlineType = shape->m_eLineType; + curr_cont->m_lUnderlineColor = shape->m_dHeight > 0.3 ? shape->m_oBrush.Color1 : shape->m_oPen.Color; + } + + else if (is_highlight) + { + curr_cont->m_pShape = shape; + curr_cont->m_bIsHighlightPresent = true; + curr_cont->m_lHighlightColor = shape->m_oBrush.Color1; + } + + else if (is_outline) + { + auto oBrush = curr_cont->m_pFontStyle->oBrush; + oBrush.Color1 = shape->m_oPen.Color; + + curr_cont->m_pFontStyle = m_pFontStyleManager->GetOrAddFontStyle(oBrush, + curr_cont->m_pFontStyle->wsFontName, + curr_cont->m_pFontStyle->dFontSize, + curr_cont->m_pFontStyle->bItalic, + curr_cont->m_pFontStyle->bBold); + + curr_cont->m_bIsShadowPresent = true; + curr_cont->m_bIsOutlinePresent = true; + } } // проверили - удаляем - if (bIsNotComplicatedFigure && (bIsLineCrossingText || bIsLineBelowText || bIsItHighlightingBackground)) + if (is_smth_true) shape_used = true; - - if (!bIsNotComplicatedFigure) - { - bool bIf1 = curr_cont->m_pFontStyle->oBrush.Color1 == c_iGreyColor; - bool bIf2 = curr_cont->m_bIsShadowPresent && curr_cont->m_bIsOutlinePresent; - bool bIf3 = eVType == eVerticalCrossingType::vctCurrentOutsideNext; - bool bIf4 = eHType == eHorizontalCrossingType::hctCurrentOutsideNext; - bool bIf5 = eHType == eHorizontalCrossingType::hctCurrentRightOfNext; - - if ((bIf1 || bIf2) && bIf3 && (bIf4 || bIf5)) - { - if (!bIf2) - { - auto oBrush = curr_cont->m_pFontStyle->oBrush; - oBrush.Color1 = shape->m_oPen.Color; - - curr_cont->m_pFontStyle = m_pFontStyleManager->GetOrAddFontStyle(oBrush, - curr_cont->m_pFontStyle->wsFontName, - curr_cont->m_pFontStyle->dFontSize, - curr_cont->m_pFontStyle->bItalic, - curr_cont->m_pFontStyle->bBold); - - curr_cont->m_bIsShadowPresent = true; - curr_cont->m_bIsOutlinePresent = true; - } - shape_used = true; - } - } } } - if(shape_used) + if (shape_used) shape = nullptr; } } - bool CPage::IsLineCrossingText(const CShape *pShape, CContText *pCont, const eHorizontalCrossingType& eHType) + bool CPage::IsLineCrossingText(std::shared_ptr pShape, std::shared_ptr pCont) { - // Height - это максимально возможный размер символа. Больше реального размера. + auto h_type = pCont->CBaseItem::GetHorizontalCrossingType(pShape.get()); double dTopBorder = pCont->m_dTop + pCont->m_dHeight / 3; bool bIf1 = pShape->m_eGraphicsType == eGraphicsType::gtRectangle && @@ -891,10 +932,10 @@ namespace NSDocxRenderer bool bIf2 = pShape->m_dTop > dTopBorder && pShape->m_dBaselinePos < pCont->m_dBaselinePos; // Условие пересечения по горизонтали - bool bIf3 = eHType != eHorizontalCrossingType::hctUnknown && - eHType != eHorizontalCrossingType::hctCurrentLeftOfNext && - eHType != eHorizontalCrossingType::hctNoCrossingCurrentLeftOfNext && - eHType != eHorizontalCrossingType::hctNoCrossingCurrentRightOfNext; + bool bIf3 = h_type != eHorizontalCrossingType::hctUnknown && + h_type != eHorizontalCrossingType::hctCurrentLeftOfNext && + h_type != eHorizontalCrossingType::hctNoCrossingCurrentLeftOfNext && + h_type != eHorizontalCrossingType::hctNoCrossingCurrentRightOfNext; // Условие для размеров по высоте bool bIf4 = pShape->m_dHeight < pCont->m_dHeight && @@ -903,8 +944,9 @@ namespace NSDocxRenderer return bIf1 && bIf2 && bIf3 && bIf4; } - bool CPage::IsLineBelowText(const CShape *pShape, CContText *pCont, const eHorizontalCrossingType& eHType) + bool CPage::IsLineBelowText(std::shared_ptr pShape, std::shared_ptr pCont) { + auto h_type = pCont->CBaseItem::GetHorizontalCrossingType(pShape.get()); bool bIf1 = (pShape->m_eGraphicsType == eGraphicsType::gtRectangle || pShape->m_eGraphicsType == eGraphicsType::gtCurve) && pShape->m_eLineType != eLineType::ltUnknown; @@ -914,10 +956,10 @@ namespace NSDocxRenderer bool bIf2 = fabs(pShape->m_dBaselinePos - pCont->m_dBaselinePos) < max_diff; //Условие пересечения по горизонтали - bool bIf3 = eHType != eHorizontalCrossingType::hctUnknown && - eHType != eHorizontalCrossingType::hctCurrentLeftOfNext && - eHType != eHorizontalCrossingType::hctNoCrossingCurrentLeftOfNext && - eHType != eHorizontalCrossingType::hctNoCrossingCurrentRightOfNext; + bool bIf3 = h_type != eHorizontalCrossingType::hctUnknown && + h_type != eHorizontalCrossingType::hctCurrentLeftOfNext && + h_type != eHorizontalCrossingType::hctNoCrossingCurrentLeftOfNext && + h_type != eHorizontalCrossingType::hctNoCrossingCurrentRightOfNext; //Условие для размеров по высоте bool bIf4 = pShape->m_dHeight < pCont->m_dHeight * 0.5 && @@ -926,11 +968,13 @@ namespace NSDocxRenderer return bIf1 && bIf2 && bIf3 && bIf4; } - bool CPage::IsItHighlightingBackground(const CShape *pShape, CContText* pCont, const eHorizontalCrossingType& eHType) + bool CPage::IsHighlight(std::shared_ptr pShape, std::shared_ptr pCont) { - double dSomeBaseLine1 = pCont->m_dBaselinePos - pCont->m_dHeight * 0.75; + auto h_type = pCont->CBaseItem::GetHorizontalCrossingType(pShape.get()); + + double dSomeBaseLine1 = pCont->m_dBaselinePos - pCont->m_dHeight * 0.70; double dSomeBaseLine2 = pCont->m_dBaselinePos - pCont->m_dHeight * 0.5; - double dSomeBaseLine3 = pCont->m_dBaselinePos - pCont->m_dHeight * 0.25; + double dSomeBaseLine3 = pCont->m_dBaselinePos - pCont->m_dHeight * 0.3; bool bIf1 = pShape->m_eGraphicsType == eGraphicsType::gtRectangle; @@ -940,10 +984,10 @@ namespace NSDocxRenderer dSomeBaseLine3 > pShape->m_dTop && dSomeBaseLine3 < pShape->m_dBaselinePos); //Условие пересечения по горизонтали - bool bIf3 = eHType != eHorizontalCrossingType::hctUnknown && - eHType != eHorizontalCrossingType::hctCurrentLeftOfNext && - eHType != eHorizontalCrossingType::hctNoCrossingCurrentLeftOfNext && - eHType != eHorizontalCrossingType::hctNoCrossingCurrentRightOfNext; + bool bIf3 = h_type != eHorizontalCrossingType::hctUnknown && + h_type != eHorizontalCrossingType::hctCurrentLeftOfNext && + h_type != eHorizontalCrossingType::hctNoCrossingCurrentLeftOfNext && + h_type != eHorizontalCrossingType::hctNoCrossingCurrentRightOfNext; //Цвета должны быть разными bool bIf4 = pCont->m_pFontStyle->oBrush.Color1 != pShape->m_oBrush.Color1; @@ -954,6 +998,25 @@ namespace NSDocxRenderer return bIf1 && bIf2 && bIf3 && bIf4 && !bIf5 && bIf6 && bIf7; } + bool CPage::IsOutline(std::shared_ptr pShape, std::shared_ptr pCont) + { + auto h_type = pCont->CBaseItem::GetHorizontalCrossingType(pShape.get()); + auto v_type = pCont->CBaseItem::GetVerticalCrossingType(pShape.get()); + + bool bIsNotComplicatedFigure = pShape->m_eGraphicsType != eGraphicsType::gtComplicatedFigure; + if (!bIsNotComplicatedFigure) + { + bool bIf1 = pCont->m_pFontStyle->oBrush.Color1 == c_iGreyColor; + bool bIf2 = v_type == eVerticalCrossingType::vctCurrentOutsideNext; + bool bIf3 = h_type == eHorizontalCrossingType::hctCurrentOutsideNext; + bool bIf4 = h_type == eHorizontalCrossingType::hctCurrentRightOfNext; + + if (bIf1 && bIf2 && (bIf3 || bIf4)) + return true; + } + return false; + } + void CPage::AddDiacriticalSymbols() { for (auto& d_sym : m_arDiacriticalSymbols) @@ -994,13 +1057,11 @@ namespace NSDocxRenderer if ((bIf1 && bIf6) || (bIf2 && bIf7) || (bIf4 && bIf8) || (bIf5 && bIf7)) { - cont->m_oText += d_sym->m_oText; + cont->AddSymBack(d_sym->GetText().at(0), 0); } else if (bIf3 && bIf7) { - NSStringUtils::CStringUTF32 oText(d_sym->m_oText); - oText += cont->m_oText; - cont->m_oText = oText; + cont->AddSymFront(d_sym->GetText().at(0), 0); } d_sym = nullptr; isBreak = true; @@ -1047,18 +1108,7 @@ namespace NSDocxRenderer void CPage::ToXml(NSStringUtils::CStringBuilder& oWriter) { - bool bIsTextShapePresent = false; - - for (size_t i = 0; i < m_arOutputObjects.size(); ++i) - { - if (m_arOutputObjects[i]->m_eType == COutputObject::eOutputType::etShape) - { - bIsTextShapePresent = true; - break; - } - } - - bool bIsNeedWP = bIsTextShapePresent || !m_arImages.empty() || !m_arShapes.empty(); + bool bIsNeedWP = !m_arImages.empty() || !m_arShapes.empty(); if (bIsNeedWP) { @@ -1090,7 +1140,7 @@ namespace NSDocxRenderer } } - void CPage::BuildLines() + void CPage::MergeConts() { for (size_t i = 0; i < m_arTextLines.size(); ++i) { @@ -1107,7 +1157,7 @@ namespace NSDocxRenderer if (pCurrCont->m_iNumDuplicates > 0) pCurrLine->m_iNumDuplicates = std::max(pCurrLine->m_iNumDuplicates, pCurrCont->m_iNumDuplicates); } - pCurrLine->MergeConts(); + pCurrLine->MergeConts(); } DetermineDominantGraphics(); } @@ -1147,13 +1197,229 @@ namespace NSDocxRenderer pDominantShape = nullptr; } } + + bool CPage::IsShapeBorderBetweenVertical(std::shared_ptr pFirst, std::shared_ptr pSecond) const noexcept + { + double left = std::min(pFirst->m_dRight, pSecond->m_dRight); + double right = std::max(pFirst->m_dLeft, pSecond->m_dLeft); + double top = std::min(pFirst->m_dTopWithMaxAscent, pSecond->m_dTopWithMaxAscent); + double bot = std::max(pFirst->m_dBotWithMaxDescent, pSecond->m_dBotWithMaxDescent); + + std::shared_ptr dummy_cont = std::make_shared(); + dummy_cont->m_dLeft = left; + dummy_cont->m_dRight = right; + dummy_cont->m_dTopWithAscent = top; + dummy_cont->m_dBotWithDescent = bot; + + double dx, dy; + return IsShapeBorderTrough(dummy_cont, dx, dy); + } + + bool CPage::IsShapeBorderBetweenHorizontal(std::shared_ptr pFirst, std::shared_ptr pSecond) const noexcept + { + double left = std::min(pFirst->m_dLeft, pSecond->m_dLeft); + double right = std::max(pFirst->m_dRight, pSecond->m_dRight); + double top = std::min(pFirst->m_dBotWithMaxDescent, pSecond->m_dBotWithMaxDescent); + double bot = std::max(pFirst->m_dTopWithMaxAscent, pSecond->m_dTopWithMaxAscent); + + std::shared_ptr dummy_cont = std::make_shared(); + dummy_cont->m_dLeft = left; + dummy_cont->m_dRight = right; + dummy_cont->m_dTopWithAscent = top; + dummy_cont->m_dBotWithDescent = bot; + + double dx, dy; + return IsShapeBorderTrough(dummy_cont, dx, dy); + } + + bool CPage::IsShapeBorderTrough(std::shared_ptr pItem, double& dXCrossing, double& dYCrossing) const noexcept + { + double left = pItem->m_dLeft; + double right = pItem->m_dRight; + double top = pItem->m_dTopWithAscent; + double bot = pItem->m_dBotWithDescent; + + for (const auto& shape : m_arShapes) + { + if (!shape) + continue; + + const double out_of_page_coeff = 1.1; + bool is_out_of_page = shape->m_dTop < 0 || + shape->m_dBaselinePos > this->m_dHeight * out_of_page_coeff || + shape->m_dLeft < 0 || + shape->m_dRight > this->m_dWidth * out_of_page_coeff; + bool is_too_big = shape->m_dWidth > c_dSHAPE_TROUGH_MAX_MM || shape->m_dHeight > c_dSHAPE_TROUGH_MAX_MM; + + if (is_too_big || is_out_of_page) + continue; + + double& s_left = shape->m_dLeft; + double& s_right = shape->m_dRight; + double& s_top = shape->m_dTop; + double& s_bot = shape->m_dBaselinePos; + + bool lines_condition = shape->m_eSimpleLineType != eSimpleLineType::sltUnknown && + !((s_right < left) || (s_left > right)) && + !((s_bot < top) || (s_top > bot)); + + bool rectangle_condition = shape->m_eGraphicsType == eGraphicsType::gtRectangle && + shape->m_eSimpleLineType == eSimpleLineType::sltUnknown && + !((s_right < left) || (s_left > right)) && + !((s_bot < top) || (s_top > bot)) && + !(s_top < top && s_bot > bot && s_left < left && s_right > right); + + if (lines_condition || rectangle_condition) + { + dXCrossing = s_left + (s_right - s_left) / 2; + dYCrossing = s_top + (s_bot - s_top) / 2; + return true; + } + } + return false; + } + + void CPage::SplitLines() + { + for (size_t index = 0; index < m_arTextLines.size(); ++index) + { + auto& line = m_arTextLines[index]; + bool next_line = false; + for (size_t i = 0; i < line->m_arConts.size(); ++i) + { + bool is_space = line->m_arConts[i] && line->m_arConts[i]->GetText().ToStdWString() == L" "; + bool is_cont_wide = line->m_arConts[i]->m_dWidth > c_dLINE_SPLIT_DISTANCE_MM; + + double x_crossing{}; + double y_crossing{}; + bool is_shape_trough = IsShapeBorderTrough(line->m_arConts[i], x_crossing, y_crossing); + + if ((i != line->m_arConts.size() - 1 && line->m_arConts[i + 1]->m_bPossibleSplit && is_space) + || (is_space && is_cont_wide) + || is_shape_trough) + { + std::vector> line_conts_first; + std::vector> line_conts_second; + + // taking last cont or not + for (size_t j = 0; j < (is_space ? i : i + 1); ++j) + if (line->m_arConts[j]) + line_conts_first.push_back(line->m_arConts[j]); + + for (size_t j = i + 1; j < line->m_arConts.size(); ++j) + if (line->m_arConts[j]) + line_conts_second.push_back(line->m_arConts[j]); + + std::shared_ptr line_first(new CTextLine()); + std::shared_ptr line_second(new CTextLine()); + + line_first->AddConts(line_conts_first); + line_second->AddConts(line_conts_second); + + if (!line_second->m_arConts.empty()) + m_arTextLines.push_back(line_second); + + if (m_arTextLines[index]->m_arConts.empty()) + { + m_arTextLines.erase(m_arTextLines.begin() + index, m_arTextLines.begin() + index + 1); + index--; + } + else + m_arTextLines[index] = line_first; + + next_line = true; + break; + } + } + if (next_line) + continue; + } + using line_ptr_t = std::shared_ptr; + std::sort(m_arTextLines.begin(), m_arTextLines.end(), [] (const line_ptr_t& a, const line_ptr_t& b) { + return a->m_dBaselinePos < b->m_dBaselinePos; + }); + } + + std::vector>> CPage::GetLinesByGroups() + { + struct Group { + double left{}; + double right{}; + double top{}; + double bot{}; + bool closed{false}; + }; + + std::vector>> line_groups; + std::vector groups; + + for (auto& line : m_arTextLines) + { + bool is_found = false; + bool is_bad_below = false; + bool is_create_new = false; + size_t insert_index = 0; + + for (size_t index = 0; index < groups.size(); ++index) + { + auto& group = groups[index]; + bool is_crossing_h = !((line->m_dRight <= group.left) || (line->m_dLeft >= group.right)); + bool is_crossing_v = !((line->m_dBotWithMaxDescent <= group.top) || (line->m_dTopWithMaxAscent >= group.bot)); + + if (!group.closed && is_crossing_h) + { + if (is_crossing_v) + { + groups[index].closed = true; + continue; + } + if (!is_found && !is_create_new) + { + is_found = true; + insert_index = index; + } + else + { + groups[insert_index].closed = true; + groups[index].closed = true; + is_create_new = true; + is_found = false; + } + } + } + if (is_found) + { + groups[insert_index].left = std::min(groups[insert_index].left, line->m_dLeft); + groups[insert_index].right = std::max(groups[insert_index].right, line->m_dRight); + groups[insert_index].bot = std::max(groups[insert_index].bot, line->m_dBaselinePos); + groups[insert_index].top = std::min(groups[insert_index].top, line->m_dTop); + line_groups[insert_index].push_back(line); + } + else + { + Group new_group; + new_group.left = line->m_dLeft; + new_group.right = line->m_dRight; + new_group.top = line->m_dTop; + new_group.bot = line->m_dBaselinePos; + new_group.closed = false; + groups.push_back(new_group); + + std::vector> line_group; + line_group.push_back(line); + line_groups.push_back(line_group); + } + } + return line_groups; + } + void CPage::BuildParagraphes() { auto no_crossing = [] (const eHorizontalCrossingType& h_type, const eVerticalCrossingType& v_type) { return h_type == eHorizontalCrossingType::hctNoCrossingCurrentLeftOfNext || - h_type == eHorizontalCrossingType::hctNoCrossingCurrentRightOfNext || - v_type == eVerticalCrossingType::vctNoCrossingCurrentAboveNext || - v_type == eVerticalCrossingType::vctNoCrossingCurrentBelowNext; + h_type == eHorizontalCrossingType::hctNoCrossingCurrentRightOfNext || + v_type == eVerticalCrossingType::vctNoCrossingCurrentAboveNext || + v_type == eVerticalCrossingType::vctNoCrossingCurrentBelowNext; }; // линии из которых сделаем шейпы @@ -1189,6 +1455,12 @@ namespace NSDocxRenderer if (!no_crossing(h_type, v_type)) { + for (auto& cont : prev_line->m_arConts) + cont->CalcSelected(); + + for (auto& cont : curr_line->m_arConts) + cont->CalcSelected(); + m_arShapes.push_back(CreateSingleLineShape(prev_line)); m_arShapes.push_back(CreateSingleLineShape(curr_line)); prev_line = nullptr; @@ -1198,7 +1470,6 @@ namespace NSDocxRenderer } } - if (m_arTextLines.empty()) return; @@ -1206,346 +1477,326 @@ namespace NSDocxRenderer auto right = MoveNullptr(m_arTextLines.begin(), m_arTextLines.end()); m_arTextLines.erase(right, m_arTextLines.end()); - using line_ptr_t = std::shared_ptr; - std::sort(m_arTextLines.begin(), m_arTextLines.end(), [] (const line_ptr_t& a, const line_ptr_t& b) { - return a->m_dBaselinePos < b->m_dBaselinePos; - }); - if (m_arTextLines.empty()) return; - auto build = [this] (const std::vector>& text_lines) { - std::vector> ar_paragraphs; + SplitLines(); + auto line_groups = GetLinesByGroups(); + std::vector> ar_paragraphs; + + double min_left{m_dWidth}; + double max_right{0.0}; + + // совпадает ли left, right, center со строкой ниже + struct Position { + bool left{false}; + bool center{false}; + bool right{false}; + }; + + // lamda to setup and add paragpraph + auto add_paragraph = [this, &max_right, &min_left, &ar_paragraphs] (std::shared_ptr& paragraph) { + + paragraph->m_dBaselinePos = paragraph->m_arLines.back()->m_dBaselinePos; + paragraph->m_dTop = paragraph->m_arLines.front()->m_dTop; + paragraph->m_dRight = max_right + c_dERROR_OF_PARAGRAPH_BORDERS_MM; + paragraph->m_dLeft = min_left; + + paragraph->m_dWidth = paragraph->m_dRight - paragraph->m_dLeft; + paragraph->m_dHeight = paragraph->m_dBaselinePos - paragraph->m_dTop; + + paragraph->m_dRightBorder = m_dWidth - max_right; + paragraph->m_dLeftBorder = min_left; + + paragraph->m_dLineHeight = paragraph->m_dHeight / paragraph->m_arLines.size(); + paragraph->m_bIsNeedFirstLineIndent = false; + paragraph->m_dFirstLine = 0; + paragraph->m_wsStyleId = m_pParagraphStyleManager->GetDefaultParagraphStyleId(*paragraph); + + paragraph->MergeLines(); + + // setting TextAlignmentType + if (paragraph->m_arLines.size() > 1) + { + Position position_curr; + position_curr.left = true; + position_curr.center = true; + position_curr.right = true; + + bool first_left = false; + + for (size_t index = 1; index < paragraph->m_arLines.size(); ++index) + { + auto& curr_line = paragraph->m_arLines[index]; + auto& prev_line = paragraph->m_arLines[index - 1]; + + // indent check + if (index == 1) + { + first_left = fabs(curr_line->m_dLeft - prev_line->m_dLeft) < c_dERROR_OF_PARAGRAPH_BORDERS_MM; + + // первая строчка левее правой + if (!first_left && prev_line->m_dLeft < curr_line->m_dLeft) + position_curr.left = false; + } + else + position_curr.left &= fabs(curr_line->m_dLeft - prev_line->m_dLeft) < c_dERROR_OF_PARAGRAPH_BORDERS_MM; + + position_curr.right &= fabs(curr_line->m_dRight - prev_line->m_dRight) < c_dERROR_OF_PARAGRAPH_BORDERS_MM; + + auto center_curr = curr_line->m_dLeft + curr_line->m_dWidth / 2; + auto center_prev = prev_line->m_dLeft + prev_line->m_dWidth / 2; + + position_curr.center &= fabs(center_curr - center_prev) < c_dCENTER_POSITION_ERROR_MM; + } + if (position_curr.left && position_curr.right && first_left) + paragraph->m_eTextAlignmentType = CParagraph::tatByWidth; + else if (position_curr.left) + paragraph->m_eTextAlignmentType = CParagraph::tatByLeft; + else if (position_curr.right) + paragraph->m_eTextAlignmentType = CParagraph::tatByRight; + else if (position_curr.center) + paragraph->m_eTextAlignmentType = CParagraph::tatByCenter; + + // indent check + if (paragraph->m_eTextAlignmentType == CParagraph::tatByLeft && !first_left) + { + paragraph->m_bIsNeedFirstLineIndent = true; + paragraph->m_dFirstLine = paragraph->m_arLines[0]->m_dLeft - paragraph->m_dLeft; + } + } + + ar_paragraphs.push_back(std::move(paragraph)); + paragraph = std::make_shared(); + + min_left = m_dWidth; + max_right = 0.0; + }; + + // lamda to add line and setup min_left/max_right + auto add_line = [&min_left, &max_right] (std::shared_ptr& paragraph, const std::shared_ptr& curr_line) { + min_left = std::min(min_left, curr_line->m_dLeft); + max_right = std::max(max_right, curr_line->m_dRight); + paragraph->m_arLines.push_back(curr_line); + }; + + auto build_paragraphs = [this, add_line, add_paragraph] (const std::vector>& text_lines) { + // ar_spacing[index]- расстояние строки до строки снизу + // если 0.0 - строка последняя + std::vector ar_spacings(text_lines.size(), 0.0); + + // позиции относительно других линий + std::vector ar_positions(text_lines.size()); + + // требуется ли отступ + std::vector ar_indents(text_lines.size(), false); + + // если ar_delims[index] == true, после строчки index нужно начинать новый параграф + std::vector ar_delims(text_lines.size(), false); double avg_spacing{0.0}; size_t avg_spacing_n{0}; - double min_left{m_dWidth}; - double max_right{0.0}; - - // совпадает ли left, right, center со строкой ниже - struct Position { - bool left{false}; - bool center{false}; - bool right{false}; - }; - // параграф будет набиваться строчками auto paragraph = std::make_shared(); - // lamda to setup and add paragpraph - auto add_paragraph = [this, &max_right, &min_left, &ar_paragraphs] (std::shared_ptr& paragraph) { + // calcs first word widths + for (auto& line : text_lines) + line->CalcFirstWordWidth(); - paragraph->m_dBaselinePos = paragraph->m_arLines.back()->m_dBaselinePos; - paragraph->m_dTop = paragraph->m_arLines.front()->m_dTop; - paragraph->m_dRight = max_right + c_dERROR_OF_PARAGRAPH_BORDERS_MM; - paragraph->m_dLeft = min_left; - - paragraph->m_dWidth = paragraph->m_dRight - paragraph->m_dLeft; - paragraph->m_dHeight = paragraph->m_dBaselinePos - paragraph->m_dTop; - - paragraph->m_dRightBorder = m_dWidth - max_right; - paragraph->m_dLeftBorder = min_left; - - paragraph->m_dLineHeight = paragraph->m_dHeight / paragraph->m_arLines.size(); - paragraph->m_bIsNeedFirstLineIndent = false; - paragraph->m_dFirstLine = 0; - paragraph->m_wsStyleId = m_pParagraphStyleManager->GetDefaultParagraphStyleId(*paragraph); - - paragraph->MergeLines(); - - // setting TextAlignmentType - if (paragraph->m_arLines.size() > 1) - { - Position position_curr; - position_curr.left = true; - position_curr.center = true; - position_curr.right = true; - - bool first_left = false; - - for (size_t index = 1; index < paragraph->m_arLines.size(); ++index) - { - auto& curr_line = paragraph->m_arLines[index]; - auto& prev_line = paragraph->m_arLines[index - 1]; - - // indent check - if (index == 1) - { - first_left = fabs(curr_line->m_dLeft - prev_line->m_dLeft) < c_dERROR_OF_PARAGRAPH_BORDERS_MM; - - // первая строчка левее правой - if (!first_left && prev_line->m_dLeft < curr_line->m_dLeft) - position_curr.left = false; - } - else - position_curr.left &= fabs(curr_line->m_dLeft - prev_line->m_dLeft) < c_dERROR_OF_PARAGRAPH_BORDERS_MM; - - position_curr.right &= fabs(curr_line->m_dRight - prev_line->m_dRight) < c_dERROR_OF_PARAGRAPH_BORDERS_MM; - - auto center_curr = curr_line->m_dLeft + curr_line->m_dWidth / 2; - auto center_prev = prev_line->m_dLeft + prev_line->m_dWidth / 2; - - position_curr.center &= fabs(center_curr - center_prev) < c_dCENTER_POSITION_ERROR_MM; - } - if (position_curr.left && position_curr.right && first_left) - paragraph->m_eTextAlignmentType = CParagraph::tatByWidth; - else if (position_curr.left) - paragraph->m_eTextAlignmentType = CParagraph::tatByLeft; - else if (position_curr.right) - paragraph->m_eTextAlignmentType = CParagraph::tatByRight; - else if (position_curr.center) - paragraph->m_eTextAlignmentType = CParagraph::tatByCenter; - - // indent check - if (paragraph->m_eTextAlignmentType == CParagraph::tatByLeft && !first_left) - { - paragraph->m_bIsNeedFirstLineIndent = true; - paragraph->m_dFirstLine = paragraph->m_arLines[0]->m_dLeft - paragraph->m_dLeft; - } - } - if (m_eTextAssociationType == TextAssociationType::tatPlainParagraph || - m_eTextAssociationType == TextAssociationType::tatPlainLine) - { - if (ar_paragraphs.empty()) - paragraph->m_dSpaceBefore = paragraph->m_dTop + c_dCORRECTION_FOR_FIRST_PARAGRAPH; - else - paragraph->m_dSpaceBefore = paragraph->m_dTop - ar_paragraphs.back()->m_dBaselinePos; - } - - ar_paragraphs.push_back(std::move(paragraph)); - paragraph = std::make_shared(); - - min_left = m_dWidth; - max_right = 0.0; - }; - - // lamda to add line and setup min_left/max_right - auto add_line = [&min_left, &max_right] (std::shared_ptr& paragraph, std::shared_ptr& curr_line) { - min_left = std::min(min_left, curr_line->m_dLeft); - max_right = std::max(max_right, curr_line->m_dRight); - paragraph->m_arLines.push_back(curr_line); - }; - - // 1 строчка в параграфе - if (m_eTextAssociationType == TextAssociationType::tatPlainLine || - m_eTextAssociationType == TextAssociationType::tatShapeLine) + // calcs spacings & positions + for (size_t index = 0; index < text_lines.size() - 1; ++index) { - for (auto& curr_line : m_arTextLines) + ar_spacings[index] = text_lines[index + 1]->m_dTop - text_lines[index]->m_dBaselinePos; + avg_spacing = (avg_spacing / (avg_spacing_n + 1)) * avg_spacing_n + (ar_spacings[index] / (avg_spacing_n + 1)); + + auto& left_curr = text_lines[index]->m_dLeft; + auto& left_next = text_lines[index + 1]->m_dLeft; + + auto& right_curr = text_lines[index]->m_dRight; + auto& right_next = text_lines[index + 1]->m_dRight; + + auto center_curr = (text_lines[index]->m_dLeft + text_lines[index]->m_dWidth / 2); + auto center_next = (text_lines[index + 1]->m_dLeft + text_lines[index + 1]->m_dWidth / 2); + + if (fabs(center_curr - center_next) < c_dCENTER_POSITION_ERROR_MM) + ar_positions[index].center = true; + if (fabs(left_curr - left_next) < c_dERROR_OF_PARAGRAPH_BORDERS_MM) + ar_positions[index].left = true; + if (fabs(right_curr - right_next) < c_dERROR_OF_PARAGRAPH_BORDERS_MM) + ar_positions[index].right = true; + } + + // spacing check + for (size_t index = 0; index < ar_spacings.size(); ++index) + { + double spacing_top = 0.0; + double spacing_bot = 0.0; + + if (index != 0) spacing_top = ar_spacings[index - 1]; + spacing_bot = ar_spacings[index]; + + if (spacing_top == 0.0) spacing_top = spacing_bot; + if (spacing_bot == 0.0) spacing_bot = spacing_top; + + if (spacing_bot > c_dLINE_DISTANCE_MAX_MM) + ar_delims[index] = true; + else if (fabs(spacing_top - spacing_bot) < c_dLINE_DISTANCE_ERROR_MM) + ar_delims[index] = false; + else { - add_line(paragraph, curr_line); - add_paragraph(paragraph); + // берем доп строчки сверху и снизу для анализа + bool same_double_top = false; + bool same_double_bot = false; + + if (index > 1) + { + double spacing_top_next = ar_spacings[index - 2]; + if (fabs(spacing_top - spacing_top_next) < c_dLINE_DISTANCE_ERROR_MM) + same_double_top = true; + } + if (index < ar_spacings.size() - 1) + { + double spacing_bot_next = ar_spacings[index + 1]; + if (fabs(spacing_bot - spacing_bot_next) < c_dLINE_DISTANCE_ERROR_MM) + same_double_bot = true; + } + + // если анализ доп строчек ничего не дал - разбиваем наиболее "вероятным" способом + if ((same_double_top == same_double_bot)) + { + if (spacing_top > spacing_bot) + ar_delims[index - 1] = true; + else if (spacing_top < spacing_bot) + ar_delims[index] = true; + } + // прикрепляем строчку к верху или низу + else + { + if (same_double_top) + ar_delims[index] = true; + else if (same_double_bot) + ar_delims[index - 1] = true; + } } } - else if (m_eTextAssociationType == TextAssociationType::tatPlainParagraph || - m_eTextAssociationType == TextAssociationType::tatParagraphToShape) + // alignment check + bool is_first_line = false; + for (size_t index = 0; index < ar_positions.size() - 1; ++index) { - // ar_spacing[index]- расстояние строки до строки снизу - // если 0.0 - строка последняя - std::vector ar_spacings(m_arTextLines.size(), 0.0); + Position& position = ar_positions[index]; - // позиции относительно других линий - std::vector ar_positions(m_arTextLines.size()); + auto& line_top = text_lines[index]; + auto& line_bot = text_lines[index + 1]; - // требуется ли отступ - std::vector ar_indents(m_arTextLines.size(), false); + if (index == 0 || ar_delims[index - 1]) + is_first_line = true; + else + is_first_line = false; - // если ar_delims[index] == true, после строчки index нужно начинать новый параграф - std::vector ar_delims(m_arTextLines.size(), false); - - // calcs spacings & positions - for (size_t index = 0; index < m_arTextLines.size() - 1; ++index) + // первая строка может быть с отступом + if (is_first_line && line_bot->m_dLeft < line_top->m_dLeft) { - ar_spacings[index] = m_arTextLines[index + 1]->m_dBaselinePos - m_arTextLines[index]->m_dTop; - avg_spacing = (avg_spacing / (avg_spacing_n + 1)) * avg_spacing_n + (ar_spacings[index] / (avg_spacing_n + 1)); - - auto& left_curr = m_arTextLines[index]->m_dLeft; - auto& left_next = m_arTextLines[index + 1]->m_dLeft; - - auto& right_curr = m_arTextLines[index]->m_dRight; - auto& right_next = m_arTextLines[index + 1]->m_dRight; - - auto center_curr = (m_arTextLines[index]->m_dLeft + m_arTextLines[index]->m_dWidth / 2); - auto center_next = (m_arTextLines[index + 1]->m_dLeft + m_arTextLines[index + 1]->m_dWidth / 2); - - if (fabs(center_curr - center_next) < c_dCENTER_POSITION_ERROR_MM) - ar_positions[index].center = true; - if (fabs(left_curr - left_next) < c_dERROR_OF_PARAGRAPH_BORDERS_MM) - ar_positions[index].left = true; - if (fabs(right_curr - right_next) < c_dERROR_OF_PARAGRAPH_BORDERS_MM) - ar_positions[index].right = true; - } - - // spacing check - for (size_t index = 0; index < ar_spacings.size(); ++index) - { - double spacing_top = 0.0; - double spacing_bot = 0.0; - - if (index != 0) spacing_top = ar_spacings[index - 1]; - spacing_bot = ar_spacings[index]; - - if (spacing_top == 0.0) spacing_top = spacing_bot; - if (spacing_bot == 0.0) spacing_bot = spacing_top; - - if (spacing_bot > c_dLINE_DISTANCE_MAX_MM) - ar_delims[index] = true; - else if (fabs(spacing_top - spacing_bot) < c_dLINE_DISTANCE_ERROR_MM) - ar_delims[index] = false; - else + // если больше трех линий - проверим третью + if (index < ar_positions.size() - 2) { - // берем доп строчки сверху и снизу для анализа - bool same_double_top = false; - bool same_double_bot = false; - - if (index > 1) - { - double spacing_top_next = ar_spacings[index - 2]; - if (fabs(spacing_top - spacing_top_next) < c_dLINE_DISTANCE_ERROR_MM) - same_double_top = true; - } - if (index < ar_spacings.size() - 1) - { - double spacing_bot_next = ar_spacings[index + 1]; - if (fabs(spacing_bot - spacing_bot_next) < c_dLINE_DISTANCE_ERROR_MM) - same_double_bot = true; - } - - // если анализ доп строчек ничего не дал - разбиваем наиболее "вероятным" способом - if ((same_double_top == same_double_bot)) - { - if (spacing_top > spacing_bot) - ar_delims[index - 1] = true; - else if (spacing_top < spacing_bot) - ar_delims[index] = true; - } - // прикрепляем строчку к верху или низу - else - { - if (same_double_top) - ar_delims[index] = true; - else if (same_double_bot) - ar_delims[index - 1] = true; - } - } - } - - // alignment check - bool is_first_line = false; - for (size_t index = 0; index < ar_positions.size() - 1; ++index) - { - Position& position = ar_positions[index]; - - auto& line_top = m_arTextLines[index]; - auto& line_bot = m_arTextLines[index + 1]; - - if (index == 0 || ar_delims[index - 1]) - is_first_line = true; - else - is_first_line = false; - - // первая строка может быть с отступом - if (is_first_line && line_bot->m_dLeft < line_top->m_dLeft) - { - // если больше трех линий - проверим третью - if (index < ar_positions.size() - 2) - { - if (!ar_delims[index] && !ar_delims[index + 1] && ar_positions[index + 1].left) - ar_indents[index] = true; - else if (!ar_delims[index] && ar_delims[index + 1]) - ar_indents[index] = true; - } - else + if (!ar_delims[index] && !ar_delims[index + 1] && ar_positions[index + 1].left) + ar_indents[index] = true; + else if (!ar_delims[index] && ar_delims[index + 1]) ar_indents[index] = true; } - - bool is_unknown = !((position.left || ar_indents[index]) || position.right || position.center); - if (is_unknown) - ar_delims[index] = true; - } - - // gap check - // - // bla-bla-bla - // text bla-bla-bla-bla - // - // bla-bla-bla text - // bla-bla-bla-bla - - double curr_max_right = m_arTextLines[0]->m_dRight; - double curr_min_left = m_arTextLines[0]->m_dLeft; - for (size_t index = 0; index < ar_positions.size() - 1; ++index) - { - Position position = ar_positions[index]; - auto& line_top = m_arTextLines[index]; - auto& line_bot = m_arTextLines[index + 1]; - - if (ar_delims[index]) - { - curr_max_right = line_bot->m_dRight; - curr_min_left = line_bot->m_dLeft; - continue; - } - - std::shared_ptr cont = line_bot->m_arConts[0]; - double line_with_first_right = line_top->m_dRight + cont->m_dFirstWordWidth; - double line_with_first_left = line_top->m_dLeft - cont->m_dFirstWordWidth; - - curr_max_right = std::max(curr_max_right, line_bot->m_dRight); - curr_min_left = std::min(curr_min_left, line_bot->m_dLeft); - - double diff = 0; - - if (position.right) - diff = line_with_first_left - curr_min_left; - else if (position.left || ar_indents[index]) - diff = curr_max_right - line_with_first_right; - else if (position.center) - continue; - - if (diff <= 0) - { -// if (diff > -c_dERROR_GAP) -// { -// auto& last_cont = line_top->m_arConts[line_top->m_arConts.size() - 1]; -// last_cont->m_bIsAddBrEnd = true; -// } -// else - continue; - } else - { - ar_delims[index] = true; - curr_max_right = line_bot->m_dRight; - curr_min_left = line_bot->m_dLeft; - } + ar_indents[index] = true; } - // на основе ar_delims разбиваем на параграфы - for (size_t index = 0; index < ar_delims.size(); ++index) + bool is_unknown = !((position.left || ar_indents[index]) || position.right || position.center); + if (is_unknown) + ar_delims[index] = true; + } + + // gap check + // + // bla-bla-bla + // text bla-bla-bla-bla + // + // bla-bla-bla text + // bla-bla-bla-bla + + double curr_max_right = text_lines[0]->m_dRight; + double curr_min_left = text_lines[0]->m_dLeft; + for (size_t index = 0; index < ar_positions.size() - 1; ++index) + { + Position position = ar_positions[index]; + auto& line_top = text_lines[index]; + auto& line_bot = text_lines[index + 1]; + + if (ar_delims[index]) { - add_line(paragraph, m_arTextLines[index]); - if (ar_delims[index] || index == ar_delims.size() - 1) - add_paragraph(paragraph); + curr_max_right = line_bot->m_dRight; + curr_min_left = line_bot->m_dLeft; + continue; + } + + std::shared_ptr cont = line_bot->m_arConts[0]; + double line_with_first_right = line_top->m_dRight + line_bot->m_dFirstWordWidth; + double line_with_first_left = line_top->m_dLeft - line_bot->m_dFirstWordWidth; + + curr_max_right = std::max(curr_max_right, line_bot->m_dRight); + curr_min_left = std::min(curr_min_left, line_bot->m_dLeft); + + double diff = 0; + + if (position.right) + diff = line_with_first_left - curr_min_left; + else if (position.left || ar_indents[index]) + diff = curr_max_right - line_with_first_right; + else if (position.center) + continue; + + if (diff <= 0) + continue; + else + { + ar_delims[index] = true; + curr_max_right = line_bot->m_dRight; + curr_min_left = line_bot->m_dLeft; } } - return ar_paragraphs; + // если между линий шейп - делим + for (size_t index = 0; index < ar_positions.size() - 1; ++index) + { + if (IsShapeBorderBetweenVertical(text_lines[index], text_lines[index + 1])) + ar_delims[index] = true; + } + + // на основе ar_delims разбиваем на параграфы + for (size_t index = 0; index < ar_delims.size(); ++index) + { + add_line(paragraph, text_lines[index]); + if (ar_delims[index] || index == ar_delims.size() - 1) + add_paragraph(paragraph); + } }; - std::vector> ar_paragraphs; - - if (m_eTextAssociationType == TextAssociationType::tatPlainParagraph || - m_eTextAssociationType == TextAssociationType::tatPlainLine) - { - ar_paragraphs = build(m_arTextLines); - } - - else if (m_eTextAssociationType == TextAssociationType::tatParagraphToShape || + // 1 строчка в параграфе + if (m_eTextAssociationType == TextAssociationType::tatPlainLine || m_eTextAssociationType == TextAssociationType::tatShapeLine) { - ar_paragraphs = build(m_arTextLines); + auto paragraph = std::make_shared(); + for (auto& curr_line : m_arTextLines) + { + add_line(paragraph, curr_line); + add_paragraph(paragraph); + } + } + + else if (m_eTextAssociationType == TextAssociationType::tatPlainParagraph || + m_eTextAssociationType == TextAssociationType::tatParagraphToShape) + { + for (auto& g : line_groups) + build_paragraphs(g); } using paragraph_ptr_t = std::shared_ptr; @@ -1556,14 +1807,45 @@ namespace NSDocxRenderer if (m_eTextAssociationType == TextAssociationType::tatPlainParagraph || m_eTextAssociationType == TextAssociationType::tatPlainLine) { - for(auto&& p : ar_paragraphs) - m_arOutputObjects.push_back(std::move(p)); + CBaseItem* prev_p = nullptr; + + size_t first_index = 0; + size_t second_index = first_index + 1; + + for (; first_index < ar_paragraphs.size(); first_index = second_index++) + { + auto& first_p = ar_paragraphs[first_index]; + if (second_index != ar_paragraphs.size()) + { + auto& second_p = ar_paragraphs[second_index]; + while (second_index < ar_paragraphs.size() && first_p->m_dBaselinePos > second_p->m_dTop) + second_index++; + } + + if (second_index - first_index == 1) + { + auto& p = ar_paragraphs[first_index]; + + if (!prev_p) + p->m_dSpaceBefore = p->m_dTop + c_dCORRECTION_FOR_FIRST_PARAGRAPH; + else + p->m_dSpaceBefore = p->m_dTop - prev_p->m_dBaselinePos; + + m_arOutputObjects.push_back(p); + prev_p = p.get(); + } + else + { + for (size_t j = first_index; j < second_index; ++j) + m_arShapes.push_back(CreateSingleParagraphShape(ar_paragraphs[j])); + } + } } else if (m_eTextAssociationType == TextAssociationType::tatParagraphToShape || - m_eTextAssociationType == TextAssociationType::tatShapeLine) + m_eTextAssociationType == TextAssociationType::tatShapeLine) { - for(auto&& p : ar_paragraphs) + for (auto& p : ar_paragraphs) m_arShapes.push_back(CreateSingleParagraphShape(p)); } } diff --git a/DocxRenderer/src/logic/Page.h b/DocxRenderer/src/logic/Page.h index 594bd18bb8..1a78ad28cc 100644 --- a/DocxRenderer/src/logic/Page.h +++ b/DocxRenderer/src/logic/Page.h @@ -44,38 +44,34 @@ namespace NSDocxRenderer std::vector> m_arShapes; std::vector m_arCompleteObjectsXml; - - std::vector> m_arOutputObjects; - - CTextLine* m_pCurrentLine {nullptr}; + std::vector> m_arOutputObjects; bool m_bIsDeleteTextClipPage {true}; bool m_bIsRecalcFontSize {true}; LONG m_lLastCommand = 0; - CPage(NSFonts::IApplicationFonts* pFonts); + CPage(); ~CPage(); void Init(NSStructures::CFont* pFont, - NSStructures::CPen* pPen, - NSStructures::CBrush* pBrush, - NSStructures::CShadow* pShadow, - NSStructures::CEdgeText* pEdge, - Aggplus::CMatrix* pMatrix, - Aggplus::CGraphicsPathSimpleConverter* pSimple, - CFontStyleManager* pStyleManager, - CFontManager *pFontManager, - CFontSelector* pFontSelector, - CParagraphStyleManager* pParagraphStyleManager); + NSStructures::CPen* pPen, + NSStructures::CBrush* pBrush, + NSStructures::CShadow* pShadow, + NSStructures::CEdgeText* pEdge, + Aggplus::CMatrix* pMatrix, + Aggplus::CGraphicsPathSimpleConverter* pSimple, + CFontStyleManager* pStyleManager, + CFontManager *pFontManager, + CFontSelector* pFontSelector, + CParagraphStyleManager* pParagraphStyleManager); void BeginCommand(DWORD lType); void Clear(); - //удаляем то, что выходит за границы страницы + // удаляем то, что выходит за границы страницы void DeleteTextClipPage(); // image commands - //набивается содержимым вектор m_arImages void WriteImage(const std::shared_ptr pInfo, double& fX, double& fY, double& fWidth, double& fHeight); // path commands @@ -89,54 +85,66 @@ namespace NSDocxRenderer //набивается содержимым вектор m_arShapes void DrawPath(LONG lType, const std::shared_ptr pInfo); - //набивается содержимым вектор m_arTextData void CollectTextData(const PUINT pUnicodes, - const PUINT pGids, - const UINT& nCount, - const double& fX, - const double& fY, - const double& fWidth, - const double& fHeight, - const double& fBaseLineOffset); + const PUINT pGids, + const UINT& nCount, + const double& fX, + const double& fY, + const double& fWidth, + const double& fHeight, + const double& fBaseLineOffset); void Analyze(); void Record(NSStringUtils::CStringBuilder& oWriter, bool bIsLastPage); private: + // methods to build text lines void BuildDiacriticalSymbols(); void BuildTextLines(); - void AddContToTextLine(std::shared_ptr pCont); - void AnalyzeTextLines(); - void AnalyzeConts(); - void DetermineStrikeoutsUnderlinesHighlights(); + void SplitLines(); + void CalcSelected(); + void BuildParagraphes(); + + std::vector>> GetLinesByGroups(); + + void MergeShapes(); + + // strikeouts, underlines, highlights, outline + void AnalyzeEffects(); + + bool IsLineCrossingText(std::shared_ptr pShape, std::shared_ptr pCont); + bool IsLineBelowText(std::shared_ptr pShape, std::shared_ptr pCont); + bool IsHighlight(std::shared_ptr pShape, std::shared_ptr pCont); + bool IsOutline(std::shared_ptr pShape, std::shared_ptr pCont); void AnalyzeDropCaps(); + void AnalyzeConts(); void AddDiacriticalSymbols(); void MergeLinesByVertAlignType(); - void DetermineTextColumns(); - - bool IsLineCrossingText(const CShape* pGraphicItem, CContText* pCont, const eHorizontalCrossingType& eHType); - bool IsLineBelowText(const CShape* pGraphicItem, CContText* pCont, const eHorizontalCrossingType& eHType); - bool IsItHighlightingBackground(const CShape* pGraphicItem, CContText* pCont, const eHorizontalCrossingType& eHType); void AnalyzeShapes(); void DetermineLinesType(); - void BuildLines(); + void MergeConts(); void DetermineDominantGraphics(); - void BuildParagraphes(); + bool IsShapeBorderBetweenVertical(std::shared_ptr pFirst, std::shared_ptr pSecond) const noexcept; + bool IsShapeBorderBetweenHorizontal(std::shared_ptr pFirst, std::shared_ptr pSecond) const noexcept; + bool IsShapeBorderTrough(std::shared_ptr pItem, double& dXCrossing, double& dYCrossing) const noexcept; std::shared_ptr CreateSingleLineShape(std::shared_ptr& pLine); std::shared_ptr CreateSingleParagraphShape(std::shared_ptr& pParagraph); - void MergeShapes(); - void CalcSelected(); - // конвертим m_arImages, m_arShapes, m_arParagraphs в xml-строку void ToXml(NSStringUtils::CStringBuilder& oWriter); void WriteSectionToFile(bool bLastPage, NSStringUtils::CStringBuilder& oWriter); + + std::shared_ptr m_pCurrCont {nullptr}; + NSStructures::CFont m_oPrevFont; + NSStructures::CBrush m_oPrevBrush; + + size_t m_nShapeOrder = 0; }; } diff --git a/DocxRenderer/src/logic/elements/BaseItem.cpp b/DocxRenderer/src/logic/elements/BaseItem.cpp index a5cc55b0b1..8ee2fb8f54 100644 --- a/DocxRenderer/src/logic/elements/BaseItem.cpp +++ b/DocxRenderer/src/logic/elements/BaseItem.cpp @@ -153,10 +153,4 @@ namespace NSDocxRenderer m_dWidth = m_dRight - m_dLeft; m_dHeight = m_dBaselinePos - m_dTop; } - - COutputObject& COutputObject::operator= (const COutputObject& oObj) - { - m_eType = oObj.m_eType; - return *this; - } } diff --git a/DocxRenderer/src/logic/elements/BaseItem.h b/DocxRenderer/src/logic/elements/BaseItem.h index 9632d1abfe..803116e9a0 100644 --- a/DocxRenderer/src/logic/elements/BaseItem.h +++ b/DocxRenderer/src/logic/elements/BaseItem.h @@ -65,24 +65,4 @@ namespace NSDocxRenderer CBaseItem& operator=(const CBaseItem& oSrc); }; - - class COutputObject : public CBaseItem - { - public: - enum class eOutputType - { - etAny = 0, - etParagraph = 1, - etShape = 2, - etTable = 3 - }; - - COutputObject() : m_eType(eOutputType::etAny) {} - COutputObject(eOutputType eType) : m_eType(eType) {} - virtual ~COutputObject() = default; - - COutputObject& operator= (const COutputObject& oObj); - - eOutputType m_eType; - }; } diff --git a/DocxRenderer/src/logic/elements/ContText.cpp b/DocxRenderer/src/logic/elements/ContText.cpp index 481a127c48..14fdff4d9d 100644 --- a/DocxRenderer/src/logic/elements/ContText.cpp +++ b/DocxRenderer/src/logic/elements/ContText.cpp @@ -5,6 +5,18 @@ namespace NSDocxRenderer { + bool IsTextOnlySpaces(const NSStringUtils::CStringUTF32& oText) + { + bool only_spaces = true; + for (size_t j = 0; j < oText.length(); ++j) + if (!IsSpaceUtf32(oText.at(j))) + { + only_spaces = false; + break; + } + return only_spaces; + } + CSelectedSizes::CSelectedSizes(const CSelectedSizes& oSelectedSizes) { *this = oSelectedSizes; @@ -69,6 +81,12 @@ namespace NSDocxRenderer m_dBotWithDescent = rCont.m_dBotWithDescent; m_oSelectedFont = rCont.m_oSelectedFont; + m_bPossibleSplit = rCont.m_bPossibleSplit; + + m_arSymWidths.clear(); + m_arSymWidths.resize(rCont.m_arSymWidths.size()); + for (size_t i = 0; i < rCont.m_arSymWidths.size(); ++i) + m_arSymWidths[i] = rCont.m_arSymWidths[i]; return *this; } @@ -96,6 +114,64 @@ namespace NSDocxRenderer } } + + size_t CContText::GetLength() const noexcept + { + return m_oText.length(); + } + + std::shared_ptr CContText::Split(size_t index) + { + const size_t len = GetLength(); + if (index >= len - 1) + return nullptr; + + auto lefts = GetSymLefts(); + + auto cont = std::make_shared(*this); + cont->m_oText = m_oText.substr(index + 1, (len - (index + 1))); + cont->m_dLeft = lefts[index + 1]; + cont->m_dWidth = cont->m_dRight - cont->m_dLeft; + + cont->m_arSymWidths.clear(); + for (size_t i = index + 1; i < len; ++i) + cont->m_arSymWidths.push_back(m_arSymWidths[i]); + + m_oText = m_oText.substr(0, index + 1); + m_dRight = cont->m_dLeft; + m_dWidth = m_dRight - m_dLeft; + m_arSymWidths.resize(index + 1); + m_bPossibleSplit = false; + + return cont; + } + std::shared_ptr CContText::Split(double dLeft) + { + if (dLeft < m_dLeft) + return nullptr; + + auto lefts = GetSymLefts(); + auto it = std::lower_bound(lefts.begin(), lefts.end(), dLeft); + + if (it == lefts.end()) + return nullptr; + + size_t index = std::distance(lefts.begin(), it); + if (index == 0) + return nullptr; + + index--; + + // if a little overlapped the next one - take the previous one + if (abs(lefts[index] - dLeft) < c_dTHE_STRING_X_PRECISION_MM) + index--; + + if (index == 0) + return nullptr; + + return Split(index); + } + eVerticalCrossingType CContText::GetVerticalCrossingType(const CContText* pCont) const noexcept { const double& this_top = m_dTopWithAscent; @@ -115,7 +191,7 @@ namespace NSDocxRenderer return eVerticalCrossingType::vctCurrentAboveNext; else if (this_top > other_top && this_bot > other_bot && - (this_top <= other_bot || fabs(this_top - other_bot) < c_dTHE_SAME_STRING_Y_PRECISION_MM)) + (this_top <= other_bot || fabs(this_top - other_bot) < c_dTHE_SAME_STRING_Y_PRECISION_MM)) return eVerticalCrossingType::vctCurrentBelowNext; else if (this_top == other_top && this_bot == other_bot && @@ -167,7 +243,7 @@ namespace NSDocxRenderer } // принудительно уменьшаем spacing чтобы текстовые линии не выходили за правую границу - // lCalculatedSpacing -= 1; + lCalculatedSpacing -= 1; if (lCalculatedSpacing != 0) { @@ -438,11 +514,119 @@ namespace NSDocxRenderer return false; } + bool CContText::IsOnlySpaces() const + { + return IsTextOnlySpaces(m_oText); + } + + void CContText::AddTextBack(const NSStringUtils::CStringUTF32& oText, const std::vector& arSymWidths) + { + bool is_space_twice = m_oText.at(m_oText.length() - 1) == c_SPACE_SYM && + oText.at(0) == c_SPACE_SYM; + + for (size_t i = 0; i < arSymWidths.size(); ++i) + { + auto& w = arSymWidths[i]; + if (i == 0 && is_space_twice) + { + m_arSymWidths.back() = m_arSymWidths.back() + arSymWidths[i]; + m_dWidth += arSymWidths[i]; + continue; + } + m_arSymWidths.push_back(w); + m_dWidth += w; + m_oText += oText.at(i); + } + m_dRight = m_dLeft + m_dWidth; + } + void CContText::AddTextFront(const NSStringUtils::CStringUTF32& oText, const std::vector& arSymWidths) + { + m_oText = oText + m_oText; + + auto ar_sym_w = m_arSymWidths; + m_arSymWidths = arSymWidths; + + for (auto& w : ar_sym_w) + m_arSymWidths.push_back(w); + } + void CContText::SetText(const NSStringUtils::CStringUTF32& oText, const std::vector& arSymWidths) + { + m_oText = oText; + m_arSymWidths.clear(); + m_dWidth = 0; + for (auto& w : arSymWidths) + { + m_arSymWidths.push_back(w); + m_dWidth += w; + } + m_dRight = m_dLeft + m_dWidth; + } + + void CContText::AddSymBack(uint32_t cSym, double dWidth) + { + bool is_space_twice = m_oText.at(m_oText.length() - 1) == c_SPACE_SYM && cSym == c_SPACE_SYM; + + if (is_space_twice) + m_arSymWidths.back() += dWidth; + else + { + m_arSymWidths.push_back(dWidth); + m_oText += cSym; + } + m_dWidth += dWidth; + m_dRight = m_dLeft + m_dWidth; + + } + void CContText::AddSymFront(uint32_t cSym, double dWidth) + { + NSStringUtils::CStringUTF32 text; + text += cSym; + text += m_oText; + m_oText = text; + m_arSymWidths.insert(m_arSymWidths.begin(), dWidth); + } + void CContText::SetSym(uint32_t cSym, double dWidth) + { + m_oText = L""; + m_oText += cSym; + m_arSymWidths.clear(); + m_arSymWidths.push_back(dWidth); + m_dWidth = dWidth; + m_dRight = m_dLeft + m_dWidth; + } + void CContText::RemoveLastSym() + { + m_oText = m_oText.substr(0, m_oText.length() - 1); + m_dWidth -= m_arSymWidths[m_arSymWidths.size() - 1]; + m_dRight = m_dLeft + m_dWidth; + m_arSymWidths.resize(m_arSymWidths.size() - 1); + } + + const NSStringUtils::CStringUTF32& CContText::GetText() const noexcept + { + return m_oText; + } + const std::vector& CContText::GetSymWidths() const noexcept + { + return m_arSymWidths; + } + const std::vector CContText::GetSymLefts() const noexcept + { + std::vector lefts; + double left = m_dLeft; + for (auto& w : m_arSymWidths) + { + lefts.push_back(left); + left += w; + } + return lefts; + } + bool CContText::CheckFontEffects - (std::shared_ptr& pFirstCont, - std::shared_ptr& pSecondCont, - eVerticalCrossingType eVType, - eHorizontalCrossingType eHType) + (std::shared_ptr& pFirstCont, + std::shared_ptr& pSecondCont, + eVerticalCrossingType eVType, + eHorizontalCrossingType eHType) { //Условие пересечения по вертикали bool bIf1 = eVType == eVerticalCrossingType::vctCurrentAboveNext; //текущий cont выше @@ -522,20 +706,20 @@ namespace NSDocxRenderer } bool CContText::CheckVertAlignTypeBetweenConts - (std::shared_ptr pFirstCont, - std::shared_ptr pSecondCont, - eVerticalCrossingType eVType, - eHorizontalCrossingType eHType) + (std::shared_ptr pFirstCont, + std::shared_ptr pSecondCont, + eVerticalCrossingType eVType, + eHorizontalCrossingType eHType) { bool bIf1 = eVType == eVerticalCrossingType::vctCurrentAboveNext || - eVType == eVerticalCrossingType::vctCurrentInsideNext; + eVType == eVerticalCrossingType::vctCurrentInsideNext; bool bIf2 = eVType == eVerticalCrossingType::vctCurrentBelowNext; bool bIf3 = (eHType == eHorizontalCrossingType::hctNoCrossingCurrentLeftOfNext || - eHType == eHorizontalCrossingType::hctCurrentLeftOfNext) && - fabs(pFirstCont->m_dRight - pSecondCont->m_dLeft) < c_dTHE_STRING_X_PRECISION_MM * 3; + eHType == eHorizontalCrossingType::hctCurrentLeftOfNext) && + fabs(pFirstCont->m_dRight - pSecondCont->m_dLeft) < c_dTHE_STRING_X_PRECISION_MM * 3; bool bIf4 = (eHType == eHorizontalCrossingType::hctNoCrossingCurrentRightOfNext || eHType == eHorizontalCrossingType::hctCurrentRightOfNext) && @@ -553,6 +737,7 @@ namespace NSDocxRenderer pSecondCont->m_pCont = pFirstCont; pFirstCont->m_eVertAlignType = eVertAlignType::vatBase; pFirstCont->m_pCont = pSecondCont; + pFirstCont->m_bPossibleSplit = false; return true; } else if (bIf2 && bIf5) @@ -561,6 +746,7 @@ namespace NSDocxRenderer pSecondCont->m_pCont = pFirstCont; pFirstCont->m_eVertAlignType = eVertAlignType::vatBase; pFirstCont->m_pCont = pSecondCont; + pFirstCont->m_bPossibleSplit = false; return true; } else if (bIf1 && bIf6) @@ -569,6 +755,7 @@ namespace NSDocxRenderer pFirstCont->m_pCont = pSecondCont; pSecondCont->m_eVertAlignType = eVertAlignType::vatBase; pSecondCont->m_pCont = pFirstCont; + pSecondCont->m_bPossibleSplit = false; return true; } else if (bIf2 && bIf6) @@ -577,19 +764,15 @@ namespace NSDocxRenderer pFirstCont->m_pCont = pSecondCont; pSecondCont->m_eVertAlignType = eVertAlignType::vatBase; pSecondCont->m_pCont = pFirstCont; + pSecondCont->m_bPossibleSplit = false; return true; } } return false; } - double CContText::CalculateWideSpace() const noexcept + double CContText::CalculateSpace() const noexcept { - return m_dSpaceWidthMM * 3; - } - - double CContText::CalculateThinSpace() const noexcept - { - return m_dSpaceWidthMM * 0.35; + return m_dSpaceWidthMM; } } diff --git a/DocxRenderer/src/logic/elements/ContText.h b/DocxRenderer/src/logic/elements/ContText.h index fb1128e6e5..60d5acde85 100644 --- a/DocxRenderer/src/logic/elements/ContText.h +++ b/DocxRenderer/src/logic/elements/ContText.h @@ -34,15 +34,14 @@ namespace NSDocxRenderer { public: // utils - std::shared_ptr m_pFontStyle{nullptr}; - CFontManager* m_pManager {nullptr}; + std::shared_ptr m_pFontStyle{nullptr}; - // background graphics - std::shared_ptr m_pShape {nullptr}; + CFontManager* m_pManager {nullptr}; + std::shared_ptr m_pShape{nullptr}; // super/sub script - std::weak_ptr m_pCont {}; - eVertAlignType m_eVertAlignType {eVertAlignType::vatUnknown}; + std::weak_ptr m_pCont {}; + eVertAlignType m_eVertAlignType {eVertAlignType::vatUnknown}; // highlights bool m_bIsStrikeoutPresent{false}; @@ -67,13 +66,11 @@ namespace NSDocxRenderer double m_dTopWithAscent{0}; double m_dBotWithDescent{0}; - NSStringUtils::CStringUTF32 m_oText{}; UINT m_iNumDuplicates{0}; bool m_bIsAddBrEnd{false}; bool m_bWriteStyleRaw{false}; - - double m_dFirstWordWidth{0}; + bool m_bPossibleSplit{false}; CContText() = default; CContText(CFontManager* pManager) : m_pManager(pManager) {} @@ -85,30 +82,52 @@ namespace NSDocxRenderer virtual void ToXmlPptx(NSStringUtils::CStringBuilder& oWriter) const override final; virtual eVerticalCrossingType GetVerticalCrossingType(const CContText* pItem) const noexcept; - // calc sizes in selected font (uses m_pFontStyle & m_pManager) + // calc sizes in selected font (uses m_oSelectedFont & m_pManager) void CalcSelected(); + size_t GetLength() const noexcept; + void AddTextBack(const NSStringUtils::CStringUTF32& oText, const std::vector& arSymWidths); + void AddTextFront(const NSStringUtils::CStringUTF32& oText, const std::vector& arSymWidths); + void SetText(const NSStringUtils::CStringUTF32& oText, const std::vector& arSymWidths); + + void AddSymBack(uint32_t cSym, double dWidth); + void AddSymFront(uint32_t cSym, double dWidth); + void SetSym(uint32_t cSym, double dWidth); + void RemoveLastSym(); + + const NSStringUtils::CStringUTF32& GetText() const noexcept; + const std::vector& GetSymWidths() const noexcept; + const std::vector GetSymLefts() const noexcept; + + std::shared_ptr Split(size_t index); + std::shared_ptr Split(double dLeft); + CContText& operator=(const CContText& rCont); bool IsEqual(const CContText* pCont) const noexcept; UINT GetNumberOfFeatures() const noexcept; bool IsDuplicate(CContText *pCont, eVerticalCrossingType eVType) const noexcept; + bool IsOnlySpaces() const; + // check font effect and delete not needed cont // return true if was deleted static bool CheckFontEffects - (std::shared_ptr& pFirstCont, - std::shared_ptr& pSecondCont, - eVerticalCrossingType eVType, - eHorizontalCrossingType eHType); + (std::shared_ptr& pFirstCont, + std::shared_ptr& pSecondCont, + eVerticalCrossingType eVType, + eHorizontalCrossingType eHType); static bool CheckVertAlignTypeBetweenConts - (std::shared_ptr pFirstCont, - std::shared_ptr pSecondCont, - eVerticalCrossingType eVType, - eHorizontalCrossingType eHType); + (std::shared_ptr pFirstCont, + std::shared_ptr pSecondCont, + eVerticalCrossingType eVType, + eHorizontalCrossingType eHType); - double CalculateWideSpace() const noexcept; - double CalculateThinSpace() const noexcept; + double CalculateSpace() const noexcept; + + private: + NSStringUtils::CStringUTF32 m_oText{}; + std::vector m_arSymWidths{}; }; } diff --git a/DocxRenderer/src/logic/elements/DropCap.h b/DocxRenderer/src/logic/elements/DropCap.h index 8ad094990f..922855a7f6 100644 --- a/DocxRenderer/src/logic/elements/DropCap.h +++ b/DocxRenderer/src/logic/elements/DropCap.h @@ -5,7 +5,7 @@ namespace NSDocxRenderer { - class CDropCap : public COutputObject + class CDropCap : public CBaseItem { public: size_t nLines; diff --git a/DocxRenderer/src/logic/elements/Image.cpp b/DocxRenderer/src/logic/elements/Image.cpp deleted file mode 100644 index 815f24923c..0000000000 --- a/DocxRenderer/src/logic/elements/Image.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "Image.h" -#include "../../resources/Constants.h" -#include - -namespace NSDocxRenderer -{ - CImage::CImage(const CImageInfo& oInfo, const std::wstring& strDstMedia) - : m_oImageInfo(oInfo), m_strPath(strDstMedia) - { - } - - void CImage::ToXml(NSStringUtils::CStringBuilder& oWriter) const - { - oWriter.WriteString(L" 0.01) - { - oWriter.WriteString(L"rotation:"); - oWriter.AddInt((int)m_dRotate); - oWriter.AddCharSafe(';'); - } - - oWriter.WriteString(L"z-index:-1;mso-position-horizontal-relative:page;mso-position-vertical-relative:page\" filled=\"f\">"); - - oWriter.WriteString(L""); - - oWriter.WriteString(L""); - } -} diff --git a/DocxRenderer/src/logic/elements/Image.h b/DocxRenderer/src/logic/elements/Image.h deleted file mode 100644 index b5dbe9fb8f..0000000000 --- a/DocxRenderer/src/logic/elements/Image.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once -#include "BaseItem.h" -#include "../../resources/ImageInfo.h" - -namespace NSDocxRenderer -{ - class CImage : public CBaseItem - { - public: - CImageInfo m_oImageInfo; - - std::wstring m_strPath {L""}; - - bool m_bIsNoFill{true}; - bool m_bIsNoStroke{true}; - bool m_bIsBehindDoc{true}; - - double m_dRotate{0.0}; - - public: - CImage() = default; - CImage(const CImageInfo& oInfo, const std::wstring& strDstMedia); - void Clear() override final {}; - void ToXml(NSStringUtils::CStringBuilder& oWriter) const override final; - void ToXmlPptx(NSStringUtils::CStringBuilder& oWriter) const override final - {} - }; -} diff --git a/DocxRenderer/src/logic/elements/Paragraph.cpp b/DocxRenderer/src/logic/elements/Paragraph.cpp index 36494e905a..703f91bf46 100644 --- a/DocxRenderer/src/logic/elements/Paragraph.cpp +++ b/DocxRenderer/src/logic/elements/Paragraph.cpp @@ -23,12 +23,14 @@ namespace NSDocxRenderer if(!m_wsStyleId.empty()) oWriter.WriteString(L""); oWriter.WriteString(L" 0) - { - oWriter.WriteString(L" w:before=\""); oWriter.AddInt(static_cast(m_dSpaceBefore * c_dMMToDx)); - oWriter.WriteString(L"\""); - } + else + oWriter.AddInt(static_cast(0)); + oWriter.WriteString(L"\""); + if (m_dSpaceAfter > 0) { @@ -192,7 +194,11 @@ namespace NSDocxRenderer while(!pLastCont) pLastCont = pLine->m_arConts[--iNumConts]; - pLastCont->m_oText += L" "; + auto text = pLastCont->GetText(); + auto last_sym = text[text.length() - 1]; + + if (last_sym != c_SPACE_SYM && m_arLines.size() != 1) + pLastCont->AddSymBack(c_SPACE_SYM, 0); } } } diff --git a/DocxRenderer/src/logic/elements/Paragraph.h b/DocxRenderer/src/logic/elements/Paragraph.h index f6b7976fc8..460a373254 100644 --- a/DocxRenderer/src/logic/elements/Paragraph.h +++ b/DocxRenderer/src/logic/elements/Paragraph.h @@ -5,7 +5,7 @@ namespace NSDocxRenderer { - class CParagraph : public COutputObject + class CParagraph : public CBaseItem { public: enum TextAlignmentType @@ -36,7 +36,7 @@ namespace NSDocxRenderer std::wstring m_wsStyleId; public: - CParagraph() : COutputObject(COutputObject::eOutputType::etParagraph) {} + CParagraph() : CBaseItem() {} virtual ~CParagraph(); virtual void Clear() override final; virtual void ToXml(NSStringUtils::CStringBuilder& oWriter) const override final; diff --git a/DocxRenderer/src/logic/elements/Shape.cpp b/DocxRenderer/src/logic/elements/Shape.cpp index 51769617ae..69b6f684a9 100644 --- a/DocxRenderer/src/logic/elements/Shape.cpp +++ b/DocxRenderer/src/logic/elements/Shape.cpp @@ -9,7 +9,6 @@ namespace NSDocxRenderer CShape::CShape() { - COutputObject::m_eType = COutputObject::eOutputType::etShape; m_nRelativeHeight = m_gRelativeHeight; m_gRelativeHeight += c_iStandartRelativeHeight; } @@ -97,10 +96,10 @@ namespace NSDocxRenderer if( // только для фигур (pShape->m_eGraphicsType == eGraphicsType::gtComplicatedFigure || - pShape->m_eGraphicsType == eGraphicsType::gtRectangle) && + pShape->m_eGraphicsType == eGraphicsType::gtRectangle) && (this->m_eGraphicsType == eGraphicsType::gtComplicatedFigure || - this->m_eGraphicsType == eGraphicsType::gtRectangle) && + this->m_eGraphicsType == eGraphicsType::gtRectangle) && // все совпадает pShape->m_eType == this->m_eType && @@ -134,6 +133,8 @@ namespace NSDocxRenderer pShape = nullptr; this->m_eGraphicsType = eGraphicsType::gtComplicatedFigure; + this->m_eLineType = eLineType::ltUnknown; + this->m_eSimpleLineType = eSimpleLineType::sltUnknown; return true; } return false; @@ -310,45 +311,49 @@ namespace NSDocxRenderer } void CShape::CheckLineType(std::shared_ptr& pFirstShape, std::shared_ptr& pSecondShape, bool bIsLast) { - if(!pFirstShape || !pSecondShape) + if (!pFirstShape || !pSecondShape) return; if (!pFirstShape->IsItFitLine() || !pSecondShape->IsItFitLine() || !pFirstShape->IsCorrelated(pSecondShape) || - fabs(pFirstShape->m_dHeight - pSecondShape->m_dHeight) > c_dGRAPHICS_ERROR_IN_LINES_MM) // линия должна быть одного размера по высоте + fabs(pFirstShape->m_dHeight - pSecondShape->m_dHeight) > c_dGRAPHICS_ERROR_IN_LINES_MM) // линия должна быть одного размера по высоте { return; } // проверка на двойную линию - if(pFirstShape->m_eLineType == eLineType::ltDouble || pFirstShape->m_eLineType == eLineType::ltWavyDouble) + if (pFirstShape->m_eLineType == eLineType::ltDouble || pFirstShape->m_eLineType == eLineType::ltWavyDouble) { - if(pFirstShape->m_eLineType == eLineType::ltDouble) + if (pFirstShape->m_eLineType == eLineType::ltDouble) { - if(pFirstShape->m_dTop < pSecondShape->m_dTop) + if (pFirstShape->m_dTop < pSecondShape->m_dTop) { pFirstShape->m_eLineType = eLineType::ltDouble; pFirstShape->RecalcWithNewItem(pSecondShape.get()); + pFirstShape->m_oVector.Join(std::move(pSecondShape->m_oVector)); pSecondShape = nullptr; } else { pSecondShape->m_eLineType = eLineType::ltDouble; pSecondShape->RecalcWithNewItem(pFirstShape.get()); + pSecondShape->m_oVector.Join(std::move(pFirstShape->m_oVector)); pFirstShape = nullptr; } } - else if(pFirstShape->m_eLineType == eLineType::ltWavyDouble) + else if (pFirstShape->m_eLineType == eLineType::ltWavyDouble) { - if(pFirstShape->m_dTop < pSecondShape->m_dTop) + if (pFirstShape->m_dTop < pSecondShape->m_dTop) { pFirstShape->m_eLineType = eLineType::ltWavyDouble; pFirstShape->RecalcWithNewItem(pSecondShape.get()); + pFirstShape->m_oVector.Join(std::move(pSecondShape->m_oVector)); pSecondShape = nullptr; } else { pSecondShape->m_eLineType = eLineType::ltWavyDouble; pSecondShape->RecalcWithNewItem(pFirstShape.get()); + pSecondShape->m_oVector.Join(std::move(pFirstShape->m_oVector)); pFirstShape = nullptr; } } @@ -365,12 +370,14 @@ namespace NSDocxRenderer { pFirstShape->m_eLineType = eLineType::ltDouble; pFirstShape->RecalcWithNewItem(pSecondShape.get()); + pFirstShape->m_oVector.Join(std::move(pSecondShape->m_oVector)); pSecondShape = nullptr; } else { pSecondShape->m_eLineType = eLineType::ltDouble; pSecondShape->RecalcWithNewItem(pFirstShape.get()); + pSecondShape->m_oVector.Join(std::move(pFirstShape->m_oVector)); pFirstShape = nullptr; } } @@ -380,12 +387,14 @@ namespace NSDocxRenderer { pFirstShape->m_eLineType = eLineType::ltWavyDouble; pFirstShape->RecalcWithNewItem(pSecondShape.get()); + pFirstShape->m_oVector.Join(std::move(pSecondShape->m_oVector)); pSecondShape = nullptr; } else { pSecondShape->m_eLineType = eLineType::ltWavyDouble; pSecondShape->RecalcWithNewItem(pFirstShape.get()); + pSecondShape->m_oVector.Join(std::move(pFirstShape->m_oVector)); pFirstShape = nullptr; } } @@ -452,6 +461,7 @@ namespace NSDocxRenderer } pFirstShape->RecalcWithNewItem(pSecondShape.get()); + pFirstShape->m_oVector.Join(std::move(pSecondShape->m_oVector)); pSecondShape = nullptr; return; } @@ -463,14 +473,14 @@ namespace NSDocxRenderer if (pSecondShape->m_eSimpleLineType == eSimpleLineType::sltHDot) { if ((pFirstShape->m_eLineType == eLineType::ltUnknown || pFirstShape->m_eLineType == eLineType::ltDotted || - pFirstShape->m_eLineType == eLineType::ltDottedHeavy) && pSecondShape->m_eLineType == eLineType::ltUnknown) + pFirstShape->m_eLineType == eLineType::ltDottedHeavy) && pSecondShape->m_eLineType == eLineType::ltUnknown) { pFirstShape->m_eLineType = pFirstShape->m_dHeight > 0.3 ? eLineType::ltDottedHeavy : eLineType::ltDotted; passed = true; } else if ((pFirstShape->m_eLineType == eLineType::ltDotDash || pFirstShape->m_eLineType == eLineType::ltDashDotHeavy || - pFirstShape->m_eLineType == eLineType::ltDotDotDash || pFirstShape->m_eLineType == eLineType::ltDashDotDotHeavy) && - pSecondShape->m_eLineType == eLineType::ltUnknown) + pFirstShape->m_eLineType == eLineType::ltDotDotDash || pFirstShape->m_eLineType == eLineType::ltDashDotDotHeavy) && + pSecondShape->m_eLineType == eLineType::ltUnknown) { pFirstShape->m_eLineType = pFirstShape->m_dHeight > 0.3 ? eLineType::ltDashDotDotHeavy : eLineType::ltDotDotDash; pFirstShape->m_eSimpleLineType = eSimpleLineType::sltHDot; @@ -480,13 +490,13 @@ namespace NSDocxRenderer else if (pSecondShape->m_eSimpleLineType == eSimpleLineType::sltHDash) { if ((pFirstShape->m_eLineType == eLineType::ltDotDash || pFirstShape->m_eLineType == eLineType::ltDashDotHeavy) && - pSecondShape->m_eLineType == eLineType::ltUnknown) + pSecondShape->m_eLineType == eLineType::ltUnknown) { pFirstShape->m_eSimpleLineType = eSimpleLineType::sltHDash; passed = true; } else if ((pFirstShape->m_eLineType == eLineType::ltDotDotDash || pFirstShape->m_eLineType == eLineType::ltDashDotDotHeavy) && - pSecondShape->m_eLineType == eLineType::ltUnknown) + pSecondShape->m_eLineType == eLineType::ltUnknown) { pFirstShape->m_eSimpleLineType = eSimpleLineType::sltHDash; passed = true; @@ -558,6 +568,7 @@ namespace NSDocxRenderer if (passed) { pFirstShape->RecalcWithNewItem(pSecondShape.get()); + pFirstShape->m_oVector.Join(std::move(pSecondShape->m_oVector)); pSecondShape = nullptr; } } @@ -947,7 +958,7 @@ namespace NSDocxRenderer void CShape::ToXmlPptx(NSStringUtils::CStringBuilder &oWriter) const { if (m_eType == eShapeType::stPicture || - m_eType == eShapeType::stVectorTexture) + m_eType == eShapeType::stVectorTexture) { // TODO: Clip path as geometry + tile!!! oWriter.WriteString(L""); diff --git a/DocxRenderer/src/logic/elements/Shape.h b/DocxRenderer/src/logic/elements/Shape.h index e6b2477b2a..4770c33b4a 100644 --- a/DocxRenderer/src/logic/elements/Shape.h +++ b/DocxRenderer/src/logic/elements/Shape.h @@ -16,7 +16,7 @@ namespace NSDocxRenderer gtNoGraphics, }; - class CShape : public COutputObject + class CShape : public CBaseItem { public: enum class eShapeType @@ -40,6 +40,7 @@ namespace NSDocxRenderer std::wstring m_strDstMedia {}; double m_dRotate {0.0}; + size_t m_nOrder {0}; bool m_bIsNoFill {true}; bool m_bIsNoStroke {true}; @@ -50,12 +51,9 @@ namespace NSDocxRenderer eSimpleLineType m_eSimpleLineType{eSimpleLineType::sltUnknown}; eLineType m_eLineType {eLineType::ltUnknown}; - std::vector> m_arOutputObjects; + std::vector> m_arOutputObjects; std::shared_ptr m_pImageInfo{nullptr}; - private: - - public: CShape(); CShape(std::shared_ptr pInfo, const std::wstring& strDstMedia); diff --git a/DocxRenderer/src/logic/elements/TextLine.cpp b/DocxRenderer/src/logic/elements/TextLine.cpp index b63318a028..385052579c 100644 --- a/DocxRenderer/src/logic/elements/TextLine.cpp +++ b/DocxRenderer/src/logic/elements/TextLine.cpp @@ -14,12 +14,18 @@ namespace NSDocxRenderer void CTextLine::Clear() { m_arConts.clear(); + m_pLine = nullptr; } void CTextLine::AddCont(std::shared_ptr oCont) { RecalcWithNewItem(oCont.get()); m_arConts.push_back(oCont); } + void CTextLine::AddConts(const std::vector>& arConts) + { + for (auto& cont : arConts) + AddCont(cont); + } bool CTextLine::IsCanBeDeleted() const { @@ -54,18 +60,18 @@ namespace NSDocxRenderer if (!pCurrent) continue; - double dSpaceDefaultSize = pCurrent->CalculateThinSpace(); - double dSpaceWideSize = pCurrent->CalculateWideSpace(); - double dDifference = fabs(pCurrent->m_dLeft - pFirst->m_dRight); + double avg_space_width = pCurrent->m_pFontStyle->GetAvgSpaceWidth(); + double space_width = avg_space_width != 0.0 ? + avg_space_width * c_dAVERAGE_SPACE_WIDTH_COEF : + pCurrent->CalculateSpace() * c_dSPACE_WIDTH_COEF; + + double dDifference = pCurrent->m_dLeft - pFirst->m_dRight; bool bIsEqual = pFirst->IsEqual(pCurrent.get()); - bool bIsBigDelta = dDifference > dSpaceDefaultSize; - bool bIsVeryBigDelta = dDifference > dSpaceWideSize; + bool bIsSpaceDelta = dDifference > space_width; + bool bIsWideSpaceDelta = dDifference > space_width * 3; - if (bIsBigDelta && pFirst->m_dFirstWordWidth == 0.0) - pFirst->m_dFirstWordWidth = pFirst->m_dWidth; - - if (bIsVeryBigDelta) + if (bIsWideSpaceDelta || (pCurrent->m_bPossibleSplit && bIsSpaceDelta)) { auto wide_space = std::make_shared(pFirst->m_pManager); @@ -74,7 +80,16 @@ namespace NSDocxRenderer wide_space->m_dLeft = pFirst->m_dRight; wide_space->m_dRight = pCurrent->m_dLeft; wide_space->m_dWidth = wide_space->m_dRight - wide_space->m_dLeft; - wide_space->m_oText = L" "; + + wide_space->m_dBaselinePos = pCurrent->m_dBaselinePos; + wide_space->m_dTop = pCurrent->m_dTop; + + wide_space->m_dTopWithAscent = pCurrent->m_dTopWithAscent; + wide_space->m_dBotWithDescent = pCurrent->m_dBotWithDescent; + + wide_space->m_dHeight = pCurrent->m_dHeight; + + wide_space->SetSym(c_SPACE_SYM, wide_space->m_dRight - wide_space->m_dLeft); wide_space->m_pFontStyle = pFirst->m_pFontStyle; wide_space->m_pShape = nullptr; wide_space->m_iNumDuplicates = 0; @@ -97,24 +112,22 @@ namespace NSDocxRenderer m_arConts.insert(m_arConts.begin() + i, wide_space); i++; - while (!m_arConts[i]) i++; + while (!m_arConts[i] && i < m_arConts.size()) i++; + if (i == m_arConts.size()) break; pFirst = m_arConts[i]; } else if (bIsEqual) { - if (!bIsBigDelta) + if (!bIsSpaceDelta) { - pFirst->m_oText += pCurrent->m_oText; + pFirst->AddTextBack(pCurrent->GetText(), pCurrent->GetSymWidths()); } else { - pFirst->m_oText += uint32_t(' '); - pFirst->m_oText += pCurrent->m_oText; + pFirst->AddSymBack(c_SPACE_SYM, pCurrent->m_dLeft - pFirst->m_dRight); + pFirst->AddTextBack(pCurrent->GetText(), pCurrent->GetSymWidths()); } - pFirst->m_dWidth = pCurrent->m_dRight - pFirst->m_dLeft; - pFirst->m_dRight = pCurrent->m_dRight; - if (pFirst->m_pCont.expired()) { pFirst->m_pCont = pCurrent->m_pCont; @@ -124,24 +137,12 @@ namespace NSDocxRenderer } else { - if (bIsBigDelta) + if (bIsSpaceDelta) { - if (!IsSpaceUtf32(pFirst->m_oText[pFirst->m_oText.length()-1]) && - !IsSpaceUtf32(pCurrent->m_oText[0])) - { - if (pFirst->GetNumberOfFeatures() <= pCurrent->GetNumberOfFeatures()) - { - pFirst->m_oText += L" "; - pFirst->m_dWidth += (pCurrent->m_dLeft - pFirst->m_dRight); - } - else - { - NSStringUtils::CStringUTF32 oNewText = L" "; - oNewText += pCurrent->m_oText; - pCurrent->m_oText = oNewText; - pCurrent->m_dWidth += (pCurrent->m_dLeft - pFirst->m_dRight); - } - } + if (pFirst->GetNumberOfFeatures() <= pCurrent->GetNumberOfFeatures()) + pFirst->AddSymBack(c_SPACE_SYM, pCurrent->m_dLeft - pFirst->m_dRight); + else + pCurrent->AddSymFront(c_SPACE_SYM, pCurrent->m_dLeft - pFirst->m_dRight); } pFirst = pCurrent; } @@ -156,6 +157,34 @@ namespace NSDocxRenderer }); } + void CTextLine::CalcFirstWordWidth() + { + bool is_done = false; + double width = 0; + for (auto& cont : m_arConts) + { + if (!cont) + continue; + + const auto& text = cont->GetText(); + auto ar_widths = cont->GetSymWidths(); + for (size_t i = 0; i < text.length(); ++i) + { + if (text.at(i) == c_SPACE_SYM) + { + m_dFirstWordWidth = width; + is_done = true; + break; + } + width += ar_widths[i]; + } + if (is_done) + break; + } + if (!is_done) + m_dFirstWordWidth = m_dWidth; + } + void CTextLine::RecalcSizes() { m_dLeft = 0.0; @@ -166,7 +195,7 @@ namespace NSDocxRenderer m_dRight = 0.0; m_dHeight = 0.0; - for(const auto& cont : m_arConts) + for (const auto& cont : m_arConts) if(cont) RecalcWithNewItem(cont.get()); } @@ -190,7 +219,7 @@ namespace NSDocxRenderer return eVerticalCrossingType::vctCurrentAboveNext; else if (this_top > other_top && this_bot > other_bot && - (this_top <= other_bot || fabs(this_top - other_bot) < c_dTHE_SAME_STRING_Y_PRECISION_MM)) + (this_top <= other_bot || fabs(this_top - other_bot) < c_dTHE_SAME_STRING_Y_PRECISION_MM)) return eVerticalCrossingType::vctCurrentBelowNext; else if (this_top == other_top && this_bot == other_bot && @@ -263,7 +292,7 @@ namespace NSDocxRenderer size_t len = 0; for (const auto& cont : m_arConts) if (cont) - len += cont->m_oText.length(); + len += cont->GetLength(); return len; } diff --git a/DocxRenderer/src/logic/elements/TextLine.h b/DocxRenderer/src/logic/elements/TextLine.h index fdb9bd2587..89f6070c21 100644 --- a/DocxRenderer/src/logic/elements/TextLine.h +++ b/DocxRenderer/src/logic/elements/TextLine.h @@ -30,6 +30,8 @@ namespace NSDocxRenderer double m_dTopWithMaxAscent{0}; double m_dBotWithMaxDescent{0}; + double m_dFirstWordWidth{0.0}; + public: CTextLine() = default; virtual ~CTextLine(); @@ -40,7 +42,9 @@ namespace NSDocxRenderer virtual eVerticalCrossingType GetVerticalCrossingType(const CTextLine* pLine) const noexcept; void AddCont(std::shared_ptr pCont); + void AddConts(const std::vector>& arConts); void MergeConts(); + void CalcFirstWordWidth(); void RecalcSizes(); void SetVertAlignType(const eVertAlignType& oType); diff --git a/DocxRenderer/src/logic/managers/FontManager.h b/DocxRenderer/src/logic/managers/FontManager.h index 04f440aeca..d998dedd6d 100644 --- a/DocxRenderer/src/logic/managers/FontManager.h +++ b/DocxRenderer/src/logic/managers/FontManager.h @@ -5,6 +5,7 @@ #include "../../../../DesktopEditor/graphics/structures.h" #include "../../../../DesktopEditor/graphics/pro/Fonts.h" #include "../../../../DesktopEditor/common/StringUTF32.h" +#include "../../../../DesktopEditor/common/StringExt.h" namespace NSDocxRenderer { @@ -129,23 +130,23 @@ namespace NSDocxRenderer void SetStringGid(const LONG& lGid); void MeasureString(const std::wstring& wsText, - double x, - double y, - double& dBoxX, - double& dBoxY, - double& dBoxWidth, - double& dBoxHeight, - MeasureType measureType) const; + double x, + double y, + double& dBoxX, + double& dBoxY, + double& dBoxWidth, + double& dBoxHeight, + MeasureType measureType) const; void MeasureStringGids(unsigned int* pGids, - unsigned int count, - double x, - double y, - double& dBoxX, - double& dBoxY, - double& dBoxWidth, - double& dBoxHeight, - MeasureType measureType) const; + unsigned int count, + double x, + double y, + double& dBoxX, + double& dBoxY, + double& dBoxWidth, + double& dBoxHeight, + MeasureType measureType) const; void ClearCache(); private: diff --git a/DocxRenderer/src/logic/managers/FontStyleManager.cpp b/DocxRenderer/src/logic/managers/FontStyleManager.cpp index 619e542d1e..368eb7949c 100644 --- a/DocxRenderer/src/logic/managers/FontStyleManager.cpp +++ b/DocxRenderer/src/logic/managers/FontStyleManager.cpp @@ -23,23 +23,23 @@ namespace NSDocxRenderer val->ToXml(oWriter); } - std::shared_ptr CFontStyleManager::GetOrAddFontStyle(const CFontStyle& oFontStyle) + std::shared_ptr CFontStyleManager::GetOrAddFontStyle(const CFontStyle& oFontStyle) { return GetOrAddFontStyle(oFontStyle.oBrush, - oFontStyle.wsFontName, - oFontStyle.dFontSize, - oFontStyle.bItalic, - oFontStyle.bBold); + oFontStyle.wsFontName, + oFontStyle.dFontSize, + oFontStyle.bItalic, + oFontStyle.bBold); } - std::shared_ptr CFontStyleManager::GetOrAddFontStyle(const NSStructures::CBrush& oBrush, - const std::wstring& wsFontName, - double dFontSize, - bool bItalic, - bool bBold) + std::shared_ptr CFontStyleManager::GetOrAddFontStyle(const NSStructures::CBrush& oBrush, + const std::wstring& wsFontName, + double dFontSize, + bool bItalic, + bool bBold) { for(auto it = m_arFontStyles.begin(); it != m_arFontStyles.end(); ++it) { - if(oBrush.Type == (*it)->oBrush.Type && + if (oBrush.Type == (*it)->oBrush.Type && oBrush.Color1 == (*it)->oBrush.Color1 && oBrush.Color2 == (*it)->oBrush.Color2 && oBrush.Alpha1 == (*it)->oBrush.Alpha1 && @@ -52,7 +52,7 @@ namespace NSDocxRenderer auto val = *it; // в начало списка - if(it != m_arFontStyles.begin()) + if (it != m_arFontStyles.begin()) { m_arFontStyles.erase(it); m_arFontStyles.push_front(val); diff --git a/DocxRenderer/src/logic/managers/FontStyleManager.h b/DocxRenderer/src/logic/managers/FontStyleManager.h index a46075fd97..8ed33ac2e8 100644 --- a/DocxRenderer/src/logic/managers/FontStyleManager.h +++ b/DocxRenderer/src/logic/managers/FontStyleManager.h @@ -14,12 +14,12 @@ namespace NSDocxRenderer void Clear(); void ToXml(NSStringUtils::CStringBuilder& oWriter); - std::shared_ptr GetOrAddFontStyle(const CFontStyle& oFontStyle); - std::shared_ptr GetOrAddFontStyle(const NSStructures::CBrush& oBrush, - const std::wstring& wsFontName, - double dFontSize, - bool bItalic, - bool bBold); + std::shared_ptr GetOrAddFontStyle(const CFontStyle& oFontStyle); + std::shared_ptr GetOrAddFontStyle(const NSStructures::CBrush& oBrush, + const std::wstring& wsFontName, + double dFontSize, + bool bItalic, + bool bBold); private: std::list> m_arFontStyles; diff --git a/DocxRenderer/src/logic/managers/ParagraphStyleManager.cpp b/DocxRenderer/src/logic/managers/ParagraphStyleManager.cpp index 97d12ff778..ec20ef41c5 100644 --- a/DocxRenderer/src/logic/managers/ParagraphStyleManager.cpp +++ b/DocxRenderer/src/logic/managers/ParagraphStyleManager.cpp @@ -52,7 +52,7 @@ namespace NSDocxRenderer void CParagraphStyleManager::ToXml(NSStringUtils::CStringBuilder& oWriter) { for(auto& val : m_arDefaultParagraphStyles) - val.ToXml(oWriter); + val.ToXml(oWriter); } } diff --git a/DocxRenderer/src/logic/styles/FontStyle.cpp b/DocxRenderer/src/logic/styles/FontStyle.cpp index 1fb978b651..2ce3b27bb6 100644 --- a/DocxRenderer/src/logic/styles/FontStyle.cpp +++ b/DocxRenderer/src/logic/styles/FontStyle.cpp @@ -115,4 +115,13 @@ namespace NSDocxRenderer oWriter.WriteString(L""); oWriter.WriteString(L""); } + void CFontStyle::UpdateAvgSpaceWidth(double dWidth) + { + dAvgSpaceWidth = (dAvgSpaceWidth / (m_nN + 1)) * m_nN + (dWidth / (m_nN + 1)); + m_nN++; + } + double CFontStyle::GetAvgSpaceWidth() const + { + return dAvgSpaceWidth; + } } diff --git a/DocxRenderer/src/logic/styles/FontStyle.h b/DocxRenderer/src/logic/styles/FontStyle.h index f0df1ab9d3..ffead73a82 100644 --- a/DocxRenderer/src/logic/styles/FontStyle.h +++ b/DocxRenderer/src/logic/styles/FontStyle.h @@ -18,6 +18,8 @@ namespace NSDocxRenderer bool operator==(const CFontStyle& oSrc); void ToXml(NSStringUtils::CStringBuilder& oWriter); + void UpdateAvgSpaceWidth(double dWidth); + double GetAvgSpaceWidth() const; std::wstring wsFontStyleId {L""}; NSStructures::CBrush oBrush; @@ -26,8 +28,11 @@ namespace NSDocxRenderer bool bItalic {false}; bool bBold {false}; + private: const std::wstring m_wsIdStart = L"fontstyle"; + double dAvgSpaceWidth {0}; + size_t m_nN {0}; }; } diff --git a/DocxRenderer/src/resources/Constants.h b/DocxRenderer/src/resources/Constants.h index c33d0e1b19..2e36ab298c 100644 --- a/DocxRenderer/src/resources/Constants.h +++ b/DocxRenderer/src/resources/Constants.h @@ -1,5 +1,6 @@ #pragma once #include "../../../DesktopEditor/common/Types.h" +#include #define USING_DELETE_DUPLICATING_CONTS 0 // 0 - все сточки-дубликаты превращаются в shape, 1 - строчки дубликаты удаляются // #define USE_DEFAULT_FONT_TO_RECALC @@ -18,8 +19,9 @@ const double c_dPtToEMU = 12700.0; const double c_dDegreeToAngle = 60000.0; const double c_dSTANDART_STRING_HEIGHT_MM = 4.2333333333333334; -const double c_dTHE_SAME_STRING_Y_PRECISION_MM = 0.01; -const double c_dLINE_DISTANCE_ERROR_MM = 0.03; +const double c_dTHE_SAME_STRING_Y_PRECISION_MM = 0.02; +const double c_dTHE_SAME_STRING_X_PRECISION_MM = 0.02; +const double c_dLINE_DISTANCE_ERROR_MM = 0.3; const double c_dERROR_OF_PARAGRAPH_BORDERS_MM = 1.0; const double c_dERROR_GAP = 1.5; const double c_dCENTER_POSITION_ERROR_MM = 1.5; @@ -28,10 +30,14 @@ const double c_dERROR_FOR_TEXT_WITH_GRAPHICS_MM = 0.1; const double c_dGRAPHICS_ERROR_MM = 0.5; const double c_dGRAPHICS_ERROR_IN_LINES_MM = 0.3; const double c_dMAX_LINE_HEIGHT_MM = 2.5; +const double c_dMAX_LINE_WITH_TEXT_ERROR_MM = 2.5; const double c_dCORRECTION_FOR_FIRST_PARAGRAPH = -1.5; -const double c_dCOEFFICIENT_LENGTHS_LINES_IN_PARAGRAPH = 0.8; const double c_dLINE_DISTANCE_MAX_MM = 50.0; +const double c_dSHAPE_TROUGH_MAX_MM = 120.0; +const double c_dLINE_SPLIT_DISTANCE_MM = 10.0; const double c_dSHAPE_X_OFFSET = 1.5; +const double c_dAVERAGE_SPACE_WIDTH_COEF = 0.9; +const double c_dSPACE_WIDTH_COEF = 0.4; const UINT c_iWhiteColor = 0xFFFFFF; const UINT c_iBlackColor = 0x000000; @@ -43,6 +49,8 @@ const double c_dSTANDART_LEFT_INDENT_MM = 30; const double c_dSTANDART_RIGHT_INDENT_MM = 15; const double c_dSTANDART_FIRSTLINE_INDENT_MM = 12.5; +const uint32_t c_SPACE_SYM = 0x20; + const UINT c_iStartingIdForImages = 6; constexpr size_t c_nAntiZero = ~0; const UINT c_iStandartRelativeHeight = 0x0400; diff --git a/DocxRenderer/src/resources/VectorGraphics.cpp b/DocxRenderer/src/resources/VectorGraphics.cpp index 442b2df7ce..96c20b932f 100644 --- a/DocxRenderer/src/resources/VectorGraphics.cpp +++ b/DocxRenderer/src/resources/VectorGraphics.cpp @@ -9,12 +9,11 @@ namespace NSDocxRenderer { CVectorGraphics::CVectorGraphics() + : m_dLeftDefault(std::numeric_limits().max()), + m_dRightDefault(std::numeric_limits().min()), + m_dTopDefault(std::numeric_limits().max()), + m_dBottomDefault(std::numeric_limits().min()) { - m_dLeftDefault = std::numeric_limits().max(); - m_dTopDefault = std::numeric_limits().max(); - m_dRightDefault = std::numeric_limits().min(); - m_dBottomDefault = std::numeric_limits().min(); - ResetBorders(); } @@ -24,7 +23,7 @@ namespace NSDocxRenderer } CVectorGraphics& CVectorGraphics::operator=(CVectorGraphics&& other) { - if(this == &other) + if (this == &other) return *this; m_arData = std::move(other.m_arData); diff --git a/DocxRenderer/src/resources/VectorGraphics.h b/DocxRenderer/src/resources/VectorGraphics.h index 89802ee95b..ad35a11b69 100644 --- a/DocxRenderer/src/resources/VectorGraphics.h +++ b/DocxRenderer/src/resources/VectorGraphics.h @@ -3,6 +3,16 @@ namespace NSDocxRenderer { + struct Point + { + double x = 0; + double y = 0; + + Point() {} + Point(double x, double y) : x(x), y(y) {} + Point(const Point& point) : x(point.x), y(point.y) {} + }; + class CVectorGraphics { public: @@ -14,12 +24,6 @@ namespace NSDocxRenderer vgtClose = 3 }; - struct Point - { - double x; - double y; - }; - struct PathCommand { eVectorGraphicsType type; @@ -59,10 +63,10 @@ namespace NSDocxRenderer double m_dRight; double m_dBottom; - double m_dLeftDefault; - double m_dTopDefault; - double m_dRightDefault; - double m_dBottomDefault; + const double m_dLeftDefault; + const double m_dTopDefault; + const double m_dRightDefault; + const double m_dBottomDefault; void ResetBorders(); }; diff --git a/DocxRenderer/src/resources/utils.h b/DocxRenderer/src/resources/utils.h index 1bab2dca82..b49cfc1571 100644 --- a/DocxRenderer/src/resources/utils.h +++ b/DocxRenderer/src/resources/utils.h @@ -15,7 +15,7 @@ inline bool IsSpaceUtf32(const uint32_t& c) return (0x20 == c || //пробел 0xA0 == c || //неразрывный пробел 0x2003 == c //Em пробел - ) ? true : false; + ); } inline bool IsSpaceUtf32(const NSStringUtils::CStringUTF32& oText) { diff --git a/MsBinaryFile/DocFile/VMLPictureMapping.cpp b/MsBinaryFile/DocFile/VMLPictureMapping.cpp index fb729a5177..10dce60a1e 100644 --- a/MsBinaryFile/DocFile/VMLPictureMapping.cpp +++ b/MsBinaryFile/DocFile/VMLPictureMapping.cpp @@ -316,6 +316,9 @@ namespace DocFileFormat //todooo oбъединить с shape_mapping + + int nColorRGBBase = 0xffffff; + for (size_t i = 0; i < options.size(); i++) { ODRAW::OfficeArtFOPTEPtr & iter = options[i]; @@ -355,7 +358,7 @@ namespace DocFileFormat if (!pict->brcBottom) { ODRAW::OfficeArtCOLORREF bottomColor((_UINT32)iter->op); - m_context->_doc->CorrectColor(bottomColor); + m_context->_doc->CorrectColor(bottomColor, nColorRGBBase); if (false == bottomColor.sColorRGB.empty()) m_pXmlWriter->WriteAttribute(L"o:borderbottomcolor", L"#" + bottomColor.sColorRGB); } @@ -364,7 +367,7 @@ namespace DocFileFormat if (!pict->brcLeft) { ODRAW::OfficeArtCOLORREF leftColor((_UINT32)iter->op); - m_context->_doc->CorrectColor(leftColor); + m_context->_doc->CorrectColor(leftColor, nColorRGBBase); if (false == leftColor.sColorRGB.empty()) m_pXmlWriter->WriteAttribute(L"o:borderleftcolor", L"#" + leftColor.sColorRGB); } @@ -373,7 +376,7 @@ namespace DocFileFormat if (!pict->brcRight) { ODRAW::OfficeArtCOLORREF rightColor((_UINT32)iter->op); - m_context->_doc->CorrectColor(rightColor); + m_context->_doc->CorrectColor(rightColor, nColorRGBBase); if (false == rightColor.sColorRGB.empty()) m_pXmlWriter->WriteAttribute(L"o:borderrightcolor", L"#" + rightColor.sColorRGB); } @@ -382,7 +385,7 @@ namespace DocFileFormat if (!pict->brcTop) { ODRAW::OfficeArtCOLORREF topColor((_UINT32)iter->op); - m_context->_doc->CorrectColor(topColor); + m_context->_doc->CorrectColor(topColor, nColorRGBBase); if (false == topColor.sColorRGB.empty()) m_pXmlWriter->WriteAttribute(L"o:bordertopcolor", L"#" + topColor.sColorRGB); } diff --git a/MsBinaryFile/DocFile/VMLShapeMapping.cpp b/MsBinaryFile/DocFile/VMLShapeMapping.cpp index 723c282537..186fc1701e 100644 --- a/MsBinaryFile/DocFile/VMLShapeMapping.cpp +++ b/MsBinaryFile/DocFile/VMLShapeMapping.cpp @@ -323,15 +323,24 @@ namespace DocFileFormat ODRAW::OfficeArtFOPTEPtr opConnectAngles; ODRAW::OfficeArtFOPTEPtr opConnectLocs; + int nColorRGBBase = 0xffffff, nFillType = 0; + + bool bFlipColors = false; + + boost::optional fill_left; + boost::optional fill_top; + boost::optional fill_right; + boost::optional fill_bottom; + for (size_t i = 0; i < options.size(); i++) { ODRAW::OfficeArtFOPTEPtr & iter = options[i]; switch (iter->opid) { - //BOOLEANS + //BOOLEANS case ODRAW::geometryBooleanProperties: { - ODRAW::GeometryBooleanProperties *booleans = dynamic_cast(iter.get()); + ODRAW::GeometryBooleanProperties* booleans = dynamic_cast(iter.get()); if (booleans->fUsefLineOK && !booleans->fLineOK) { bStroked = false; @@ -352,7 +361,7 @@ namespace DocFileFormat break; case ODRAW::fillStyleBooleanProperties: { - ODRAW::FillStyleBooleanProperties *booleans = dynamic_cast(iter.get()); + ODRAW::FillStyleBooleanProperties* booleans = dynamic_cast(iter.get()); if (booleans->fUsefFilled && !booleans->fFilled) { bFilled = false; @@ -365,7 +374,7 @@ namespace DocFileFormat }break; case ODRAW::lineStyleBooleanProperties: { - ODRAW::LineStyleBooleanProperties *booleans = dynamic_cast(iter.get()); + ODRAW::LineStyleBooleanProperties* booleans = dynamic_cast(iter.get()); if (booleans->fUsefLine && !booleans->fLine) { bStroked = false; @@ -383,14 +392,14 @@ namespace DocFileFormat break; case ODRAW::groupShapeBooleanProperties: { - ODRAW::GroupShapeBooleanProperties *booleans = dynamic_cast(iter.get()); + ODRAW::GroupShapeBooleanProperties* booleans = dynamic_cast(iter.get()); if (booleans->fUsefLayoutInCell) { layoutInCell = booleans->fLayoutInCell; } } break; - // GEOMETRY + // GEOMETRY case ODRAW::shapePath: { bHavePath = true; @@ -483,7 +492,7 @@ namespace DocFileFormat case ODRAW::lineColor: { ODRAW::OfficeArtCOLORREF lineColor((_UINT32)iter->op); - m_context->_doc->CorrectColor(lineColor); + m_context->_doc->CorrectColor(lineColor, nColorRGBBase); if (false == lineColor.sColorRGB.empty() && !pShape->fBackground) m_pXmlWriter->WriteAttribute(L"strokecolor", (std::wstring(L"#") + lineColor.sColorRGB)); }break; @@ -542,18 +551,20 @@ namespace DocFileFormat case 3: m_pXmlWriter->WriteAttribute(L"o:connectortype", L"none"); break; } }break; - // FILL + // FILL case ODRAW::fillColor: { ODRAW::OfficeArtCOLORREF fillColor((_UINT32)iter->op); - m_context->_doc->CorrectColor(fillColor); + m_context->_doc->CorrectColor(fillColor, nColorRGBBase); if (false == fillColor.sColorRGB.empty()) m_pXmlWriter->WriteAttribute(L"fillcolor", (std::wstring(L"#") + fillColor.sColorRGB)); + + nColorRGBBase = fillColor.nColorRGB; }break; case ODRAW::fillBackColor: { ODRAW::OfficeArtCOLORREF fillBackColor((_UINT32)iter->op); - m_context->_doc->CorrectColor(fillBackColor); + m_context->_doc->CorrectColor(fillBackColor, nColorRGBBase); if (false == fillBackColor.sColorRGB.empty()) appendValueAttribute(&m_fill, L"color2", (std::wstring(L"#") + fillBackColor.sColorRGB)); @@ -573,13 +584,47 @@ namespace DocFileFormat }break; case ODRAW::fillFocus: { - appendValueAttribute(&m_fill, L"focus", (std::to_wstring(iter->op) + L"%")); - appendValueAttribute(&m_fill, L"focusposition", L".5, .5"); + appendValueAttribute(&m_fill, L"focus", (std::to_wstring(iter->op) + L"%")); appendValueAttribute(&m_fill, L"focussize", L""); }break; case ODRAW::fillType: { - appendValueAttribute(&m_fill, L"type", getFillType(iter->op)); + nFillType = iter->op; + appendValueAttribute(&m_fill, L"type", getFillType(nFillType)); + if (nFillType == 6) + { + fill_top = 0.5; + fill_left = 0.5; + } + + //if (nFillType == 7) bFlipColors = true; + }break; + case ODRAW::fillToLeft: + { + ODRAW::FixedPoint* point = dynamic_cast(iter.get()); + if (point) fill_left = point->dVal; + }break; + case ODRAW::fillToTop: + { + ODRAW::FixedPoint* point = dynamic_cast(iter.get()); + if (point) fill_top = point->dVal; + }break; + case ODRAW::fillToRight: + { + ODRAW::FixedPoint* point = dynamic_cast(iter.get()); + if (point) fill_right = point->dVal; + }break; + case ODRAW::fillToBottom: + { + ODRAW::FixedPoint* point = dynamic_cast(iter.get()); + if (point) fill_bottom = point->dVal; + }break; + case ODRAW::fillRectLeft: + case ODRAW::fillRectTop: + case ODRAW::fillRectRight: + case ODRAW::fillRectBottom: + { + }break; case ODRAW::fillBlip: { @@ -630,7 +675,7 @@ namespace DocFileFormat case ODRAW::shadowColor: { ODRAW::OfficeArtCOLORREF shadowColor((_UINT32)iter->op); - m_context->_doc->CorrectColor(shadowColor); + m_context->_doc->CorrectColor(shadowColor, nColorRGBBase); if (false == shadowColor.sColorRGB.empty()) appendValueAttribute(&m_shadow, L"color", (std::wstring(L"#") + shadowColor.sColorRGB)); }break; @@ -932,6 +977,18 @@ namespace DocFileFormat } } + if (fill_top || fill_left) + { + std::wstring focusposition; + if (fill_left) focusposition += FormatUtils::DoubleToFormattedWideString(*fill_left, L"%.2f"); + if (fill_top) + { + focusposition += L","; + focusposition += FormatUtils::DoubleToFormattedWideString(*fill_top, L"%.2f"); + } + appendValueAttribute(&m_fill, L"focusposition", focusposition); + } + ODRAW::PVertices* pVP = dynamic_cast(opVerticles.get()); ODRAW::PSegmentInfo* pSI = dynamic_cast(opSegmentInfo.get()); if (pVP && pSI) diff --git a/MsBinaryFile/DocFile/WordDocument.cpp b/MsBinaryFile/DocFile/WordDocument.cpp index 4de69019f8..8c6497f6ec 100644 --- a/MsBinaryFile/DocFile/WordDocument.cpp +++ b/MsBinaryFile/DocFile/WordDocument.cpp @@ -1029,14 +1029,40 @@ namespace DocFileFormat return encodingChars; } } - void WordDocument::CorrectColor(ODRAW::OfficeArtCOLORREF & color) + void WordDocument::CorrectColor(ODRAW::OfficeArtCOLORREF & color, int base_color) { -#if 0 + struct _color + { + _color(unsigned char nR, unsigned char nG, unsigned char nB) + { + SetRGB(nR, nG, nB); + } + _color() {} + int nRGB = 0; + std::wstring sRGB; + int index = -1; + bool bScheme = false; + + void SetRGB(unsigned char nR, unsigned char nG, unsigned char nB) + { + nRGB = (nR << 16) | (nG << 8) | nB; + sRGB = STR::toRGB(nR, nG, nB); + + index = -1; + } + + unsigned char GetB() { return (unsigned char)(nRGB); } + unsigned char GetG() { return (unsigned char)(nRGB >> 8); } + unsigned char GetR() { return (unsigned char)(nRGB >> 16); } + + double opacity = 0; + }; + if (false == color.sColorRGB.empty()) return; if (color.fSysIndex) { - oox::_color sys_color; + _color sys_color; _UINT32 nColorCode = color.index; unsigned short nParameter = (unsigned short)((nColorCode >> 16) & 0x00ff); // the HiByte of nParameter is not zero, an exclusive AND is helping :o @@ -1045,17 +1071,20 @@ namespace DocFileFormat unsigned short nColorIndex = (unsigned short)(nColorCode & 0x00ff); unsigned short nPropColor = 0; - _UINT32 systemColors[25] = + _UINT32 systemColors[25] = { 0xc0c0c0, 0x008080, 0x000080, 0x808080, 0xc0c0c0, 0xffffff, 0x000000, 0x000000, 0x000000, 0xffffff, 0xc0c0c0, 0xc0c0c0, 0x808080, 0x000080, 0xffffff, 0xc0c0c0, 0x808080, 0x808080, 0x000000, 0xc0c0c0, 0xffffff, 0x000000, 0xc0c0c0, 0x000000, 0xffffc0 }; - - if (nColorIndex < 25) + if (nColorIndex == 0xf0) { - sys_color.SetRGB((unsigned char)(systemColors[nColorIndex]>>16), (unsigned char)(systemColors[nColorIndex]>>8), (unsigned char)(systemColors[nColorIndex])); + sys_color.SetRGB((unsigned char)(base_color), (unsigned char)(base_color >> 8), (unsigned char)(base_color >> 16)); + } + else if (nColorIndex < 25) + { + sys_color.SetRGB((unsigned char)(systemColors[nColorIndex] >> 16), (unsigned char)(systemColors[nColorIndex] >> 8), (unsigned char)(systemColors[nColorIndex])); } else return; @@ -1083,7 +1112,7 @@ namespace DocFileFormat BYTE B = static_cast((nInvParameter + (nParameter * sys_color.GetB())) >> 8); sys_color.SetRGB(R, G, B); - }break; + }break; case 0x03: // add grey level RGB(p,p,p) { short nR = (short)sys_color.GetR() + (short)nParameter; @@ -1095,7 +1124,7 @@ namespace DocFileFormat if (nB > 0x00ff) nB = 0x00ff; sys_color.SetRGB((BYTE)nR, (BYTE)nG, (BYTE)nB); - }break; + }break; case 0x04: // substract grey level RGB(p,p,p) { short nR = (short)sys_color.GetR() - (short)nParameter; @@ -1105,7 +1134,7 @@ namespace DocFileFormat if (nG < 0) nG = 0; if (nB < 0) nB = 0; sys_color.SetRGB((BYTE)nR, (BYTE)nG, (BYTE)nB); - } break; + } break; case 0x05: // substract from gray level RGB(p,p,p) { short nR = (short)nParameter - (short)sys_color.GetR(); @@ -1115,7 +1144,7 @@ namespace DocFileFormat if (nG < 0) nG = 0; if (nB < 0) nB = 0; sys_color.SetRGB((BYTE)nR, (BYTE)nG, (BYTE)nB); - }break; + }break; case 0x06: // per component: black if < p, white if >= p { BYTE R = sys_color.GetR() < nParameter ? 0x00 : 0xff; @@ -1123,7 +1152,7 @@ namespace DocFileFormat BYTE B = sys_color.GetB() < nParameter ? 0x00 : 0xff; sys_color.SetRGB(R, G, B); - }break; + }break; } if (nAdditionalFlags & 0x40) // top-bit invert sys_color.SetRGB(sys_color.GetR() ^ 0x80, sys_color.GetG() ^ 0x80, sys_color.GetB() ^ 0x80); @@ -1141,7 +1170,6 @@ namespace DocFileFormat // color.sColorRGB = it->second; // } //} -#endif } } diff --git a/MsBinaryFile/DocFile/WordDocument.h b/MsBinaryFile/DocFile/WordDocument.h index e49bc56ae5..683a60c7a7 100644 --- a/MsBinaryFile/DocFile/WordDocument.h +++ b/MsBinaryFile/DocFile/WordDocument.h @@ -69,11 +69,11 @@ namespace CRYPT namespace DocFileFormat { - class WordDocument: public IVisitable + class WordDocument : public IVisitable { friend class FootnotesMapping; friend class EndnotesMapping; - friend class CommentsMapping; + friend class CommentsMapping; friend class Converter; friend class CharacterPropertiesMapping; friend class DocumentMapping; @@ -94,16 +94,16 @@ namespace DocFileFormat friend class WordprocessingDocument; public: - WordDocument (const std::wstring & tempFolder, const int userLCID); + WordDocument(const std::wstring& tempFolder, const int userLCID); virtual ~WordDocument(); - _UINT32 LoadDocument(const std::wstring & fileName, const std::wstring & password); + _UINT32 LoadDocument(const std::wstring& fileName, const std::wstring& password); int nWordVersion; int nDocumentCodePage; bool bDocumentCodePage; int nFontsCodePage; - + inline StructuredStorageReader* GetStorage() const { return m_pStorage; @@ -115,16 +115,16 @@ namespace DocFileFormat private: bool LoadDocumentFlat(); - bool DecryptOfficeFile (CRYPT::Decryptor* Decryptor); - - bool DecryptStream (std::wstring streamName_open, POLE::Storage* storageIn, std::wstring streamName_create, std::shared_ptr storageOut, CRYPT::Decryptor* Decryptor, bool bDecrypt); - void DecryptStream (int level, std::wstring streamName, POLE::Storage* storageIn, std::shared_ptr storageOut, CRYPT::Decryptor* Decryptor); - - inline OfficeArtContent* GetOfficeArt () + bool DecryptOfficeFile(CRYPT::Decryptor* Decryptor); + + bool DecryptStream(std::wstring streamName_open, POLE::Storage* storageIn, std::wstring streamName_create, std::shared_ptr storageOut, CRYPT::Decryptor* Decryptor, bool bDecrypt); + void DecryptStream(int level, std::wstring streamName, POLE::Storage* storageIn, std::shared_ptr storageOut, CRYPT::Decryptor* Decryptor); + + inline OfficeArtContent* GetOfficeArt() { return officeArtContent; } - + inline int FindFileCharPos(int cp) { if (FIB->m_FibBase.fComplex) @@ -138,41 +138,41 @@ namespace DocFileFormat else { int fc = cp + FIB->m_FibBase.fcMin; - if (fc > FIB->m_FibBase.fcMac) + if (fc > FIB->m_FibBase.fcMac) return -1; return fc; } } - std::vector* GetEncodingChars (int fcStart, int fcEnd); - std::vector* GetChars (int fcStart, int fcEnd, int cp); - - std::vector* GetFileCharacterPositions ( int fcMin, int fcMax ); - std::vector* GetCharacterPropertyExceptions ( int fcMin, int fcMax ); - + std::vector* GetEncodingChars(int fcStart, int fcEnd); + std::vector* GetChars(int fcStart, int fcEnd, int cp); + + std::vector* GetFileCharacterPositions(int fcMin, int fcMax); + std::vector* GetCharacterPropertyExceptions(int fcMin, int fcMax); + void Clear(); MS_LCID_converter m_lcidConverter; - + std::wstring m_sFileName; - std::wstring m_sPassword; + std::wstring m_sPassword; std::wstring m_sTempFolder; std::wstring m_sTempDecryptFileName; int m_nUserLCID; std::wstring m_sXmlApp; std::wstring m_sXmlCore; - POLE::Stream * WordDocumentStream; // The stream "WordDocument" - POLE::Stream * TableStream; // The stream "0Table" or "1Table" - POLE::Stream * DataStream; // The stream called "Data" - StructuredStorageReader * m_pStorage; //POLE::Storage* Storage - - std::vector * Text; // All text of the Word document - std::vector * AllPapxFkps; // A list of all FKPs that contain PAPX - std::vector * AllChpxFkps; // A list of all FKPs that contain CHPX - - std::map * AllPapx; // The value is the PAPX that formats the paragraph. - std::map * AllSepx; // The value is the SEPX that formats the section. - std::vector * AllPapxVector;// A vector to quick find in AllPapx + POLE::Stream* WordDocumentStream; // The stream "WordDocument" + POLE::Stream* TableStream; // The stream "0Table" or "1Table" + POLE::Stream* DataStream; // The stream called "Data" + StructuredStorageReader* m_pStorage; //POLE::Storage* Storage + + std::vector* Text; // All text of the Word document + std::vector* AllPapxFkps; // A list of all FKPs that contain PAPX + std::vector* AllChpxFkps; // A list of all FKPs that contain CHPX + + std::map* AllPapx; // The value is the PAPX that formats the paragraph. + std::map* AllSepx; // The value is the SEPX that formats the section. + std::vector* AllPapxVector;// A vector to quick find in AllPapx std::map PictureBulletsCPsMap; @@ -181,79 +181,79 @@ namespace DocFileFormat struct _bmkStartEnd { int start; - int end; + int end; _UINT32 bookmarkId; }; std::vector<_bmkStartEnd> BookmarkStartEndCPs; std::vector<_bmkStartEnd> BookmarkProtStartEndCPs; std::vector<_bmkStartEnd> AnnotStartEndCPs; - + std::map mapAnnotBookmarks; //id, index std::map mapProtBookmarks; - FileInformationBlock * FIB; - StyleSheet * Styles; // The style sheet of the document - PieceTable * m_PieceTable; // PieceTable PieceTable; - ListFormatOverrideTable * listFormatOverrideTable; // lists and numberings in the document. - HeaderAndFooterTable * headerAndFooterTable; - AnnotationOwnerList * AnnotationOwners; - ListTable * listTable; // list numberings in the document. - WordDocumentProperties * DocProperties; - EncryptionHeader * encryptionHeader; - OfficeArtContent * officeArtContent; // info about the drawings in the document. + FileInformationBlock* FIB; + StyleSheet* Styles; // The style sheet of the document + PieceTable* m_PieceTable; // PieceTable PieceTable; + ListFormatOverrideTable* listFormatOverrideTable; // lists and numberings in the document. + HeaderAndFooterTable* headerAndFooterTable; + AnnotationOwnerList* AnnotationOwners; + ListTable* listTable; // list numberings in the document. + WordDocumentProperties* DocProperties; + EncryptionHeader* encryptionHeader; + OfficeArtContent* officeArtContent; // info about the drawings in the document. - StringTable *RevisionAuthorTable; - StringTable *FontTable; // A list of all font names, used in the doucument - StringTable *BookmarkNames; - StringTable *AutoTextNames; - StringTable *AssocNames; - StringTable *BkmkAnnotNames; - StringTable *Captions; - StringTable *AutoCaptions; - - StringTableEx *BkmkProt; - StringTable *BkmkProtUser; + StringTable* RevisionAuthorTable; + StringTable* FontTable; // A list of all font names, used in the doucument + StringTable* BookmarkNames; + StringTable* AutoTextNames; + StringTable* AssocNames; + StringTable* BkmkAnnotNames; + StringTable* Captions; + StringTable* AutoCaptions; - Plex *IndividualFootnotesPlex; //A plex of locations of individual footnotes - Plex *FootnoteReferenceCharactersPlex; //A plex of footnote reference characters - - Plex *IndividualEndnotesPlex; //A plex of locations of individual endnotes - Plex *EndnoteReferenceCharactersPlex; //A plex of endnote reference characters - - Plex *HeaderStoriesPlex; //A plex of the header document - Plex *IndividualCommentsPlex; // A plex with all ATRDPre10 structs - - Plex *TextboxIndividualPlex; - Plex *TextboxBreakPlex; // Describes the breaks inside the textbox subdocument - Plex *TextboxBreakPlexHeader; // Describes the breaks inside the header textbox subdocument - - Plex *OutlineListDescriptorPlex; - Plex *OfficeDrawingPlex; - Plex *OfficeDrawingPlexHeader; - - Plex *SectionPlex; - - Plex *BookmarkStartPlex; - Plex *BookmarkEndPlex; + StringTableEx* BkmkProt; + StringTable* BkmkProtUser; - Plex *AnnotStartPlex; - Plex *AnnotEndPlex; + Plex* IndividualFootnotesPlex; //A plex of locations of individual footnotes + Plex* FootnoteReferenceCharactersPlex; //A plex of footnote reference characters - Plex *BookmarkProtStartPlex; - Plex *BookmarkProtEndPlex; + Plex* IndividualEndnotesPlex; //A plex of locations of individual endnotes + Plex* EndnoteReferenceCharactersPlex; //A plex of endnote reference characters - Plex *ListPlex; - Plex *FieldsPlex; - Plex *FootnoteDocumentFieldsPlex; - Plex *EndnoteDocumentFieldsPlex; - Plex *HeadersAndFootersDocumentFieldsPlex; - Plex *AnnotationsFieldsPlex; - Plex *AnnotationsReferencePlex; - Plex *AutoTextPlex; - + Plex* HeaderStoriesPlex; //A plex of the header document + Plex* IndividualCommentsPlex; // A plex with all ATRDPre10 structs - AnnotationReferenceExDescriptors *AnnotationsReferencesEx; -//------------------------------------------------------------------------------ - void CorrectColor(ODRAW::OfficeArtCOLORREF & color); + Plex* TextboxIndividualPlex; + Plex* TextboxBreakPlex; // Describes the breaks inside the textbox subdocument + Plex* TextboxBreakPlexHeader; // Describes the breaks inside the header textbox subdocument + + Plex* OutlineListDescriptorPlex; + Plex* OfficeDrawingPlex; + Plex* OfficeDrawingPlexHeader; + + Plex* SectionPlex; + + Plex* BookmarkStartPlex; + Plex* BookmarkEndPlex; + + Plex* AnnotStartPlex; + Plex* AnnotEndPlex; + + Plex* BookmarkProtStartPlex; + Plex* BookmarkProtEndPlex; + + Plex* ListPlex; + Plex* FieldsPlex; + Plex* FootnoteDocumentFieldsPlex; + Plex* EndnoteDocumentFieldsPlex; + Plex* HeadersAndFootersDocumentFieldsPlex; + Plex* AnnotationsFieldsPlex; + Plex* AnnotationsReferencePlex; + Plex* AutoTextPlex; + + + AnnotationReferenceExDescriptors* AnnotationsReferencesEx; + //------------------------------------------------------------------------------ + void CorrectColor(ODRAW::OfficeArtCOLORREF& color, int base_color); }; } diff --git a/MsBinaryFile/XlsFile/Converter/XlsConverter.cpp b/MsBinaryFile/XlsFile/Converter/XlsConverter.cpp index e95a05c8c5..f91c255d65 100644 --- a/MsBinaryFile/XlsFile/Converter/XlsConverter.cpp +++ b/MsBinaryFile/XlsFile/Converter/XlsConverter.cpp @@ -138,6 +138,7 @@ XlsConverter::XlsConverter() is_older_version = false; is_encrypted = false; } + XlsConverter::XlsConverter(const std::wstring & xlsFileName, const std::wstring & xlsxFilePath, const std::wstring & password, const std::wstring & fontsPath, const std::wstring & tempPath, const int lcid_user, bool & bMacros) { xlsx_path = xlsxFilePath; @@ -224,8 +225,38 @@ XlsConverter::XlsConverter(const std::wstring & xlsFileName, const std::wstring XLS::StreamCacheReaderPtr workbook_stream(new XLS::CFStreamCacheReader(xls_file->getWorkbookStream(), xls_global_info)); xls_document = boost::shared_ptr(new XLS::WorkbookStreamObject(workbook_code_page)); - XLS::BinReaderProcessor proc(workbook_stream, xls_document.get() , true); - proc.mandatory(*xls_document.get()); + XLS::BinReaderProcessor workbook_proc(workbook_stream, xls_document.get() , true); + if (false == workbook_proc.mandatory(*xls_document.get())) + { + // test open list + xls_file->getWorkbookStream()->seekFromBegin(0); + XLS::StreamCacheReaderPtr worksheet_stream(new XLS::CFStreamCacheReader(xls_file->getWorkbookStream(), xls_global_info)); + + XLS::BaseObjectPtr worksheet_object = XLS::BaseObjectPtr(new XLS::WorksheetSubstream(0)); + XLS::BinReaderProcessor worksheet_proc(worksheet_stream, xls_document.get(), true); + if (worksheet_proc.mandatory(*worksheet_object.get())) + { + XLS::WorksheetSubstream* worksheet = dynamic_cast(worksheet_object.get()); + XLS::WorkbookStreamObject* workbook = dynamic_cast(xls_document.get()); + if (workbook) + { + workbook->m_arWorksheetSubstream.push_back(worksheet_object); + + workbook->m_GlobalsSubstream = XLS::BaseObjectPtr(new XLS::GlobalsSubstream(0)); + + XLS::GlobalsSubstream* globals = dynamic_cast(workbook->m_GlobalsSubstream.get()); + if (globals) + { + globals->m_Formating = worksheet->m_Formating; + globals->UpdateXFC(); + } + } + } + else + { + return; //error + } + } if (xls_global_info->decryptor) { @@ -608,7 +639,8 @@ void XlsConverter::convert_common (XLS::CommonSubstream* sheet) void XlsConverter::convert (XLS::WorksheetSubstream* sheet) { if (sheet == NULL) return; - + if (xls_global_info->sheets_info.empty()) return; + std::wstring name = xls_global_info->sheets_info[sheet->ws_index_].name; if (name.empty()) name = L"Sheet_" + std::to_wstring(sheet->ws_index_ + 1); diff --git a/MsBinaryFile/XlsFile/Converter/xlsx_drawing_context.cpp b/MsBinaryFile/XlsFile/Converter/xlsx_drawing_context.cpp index f0d2708d5e..c22f4b5b85 100644 --- a/MsBinaryFile/XlsFile/Converter/xlsx_drawing_context.cpp +++ b/MsBinaryFile/XlsFile/Converter/xlsx_drawing_context.cpp @@ -81,13 +81,7 @@ namespace oox { 0x00666666, 0x00C0C0C0, 0x00DDDDDD, 0x00C0C0C0, 0x00888888, 0x00FFFFFF, 0x00CCCCCC, 0x00000000 }; - void _color::SetRGB(unsigned char nR, unsigned char nG, unsigned char nB) - { - nRGB = (nR<<16) | (nG<<8) | nB; - sRGB = STR::toRGB(nR, nG, nB); - index = -1; - } //----------------------------------------------------------------------------------------------------- class xlsx_drawing_context_handle::Impl { diff --git a/MsBinaryFile/XlsFile/Converter/xlsx_drawing_context.h b/MsBinaryFile/XlsFile/Converter/xlsx_drawing_context.h index d63512cd2c..7179902998 100644 --- a/MsBinaryFile/XlsFile/Converter/xlsx_drawing_context.h +++ b/MsBinaryFile/XlsFile/Converter/xlsx_drawing_context.h @@ -94,7 +94,13 @@ struct _color int index = -1; bool bScheme = false; - void SetRGB(unsigned char nR, unsigned char nG, unsigned char nB); + void SetRGB(unsigned char nR, unsigned char nG, unsigned char nB) + { + nRGB = (nR << 16) | (nG << 8) | nB; + sRGB = STR::toRGB(nR, nG, nB); + + index = -1; + } unsigned char GetB() { return (unsigned char )(nRGB);} unsigned char GetG() { return (unsigned char )(nRGB>>8);} diff --git a/MsBinaryFile/XlsFile/Format/Auxiliary/HelpFunc.cpp b/MsBinaryFile/XlsFile/Format/Auxiliary/HelpFunc.cpp index 682aea7510..883f533a50 100644 --- a/MsBinaryFile/XlsFile/Format/Auxiliary/HelpFunc.cpp +++ b/MsBinaryFile/XlsFile/Format/Auxiliary/HelpFunc.cpp @@ -765,10 +765,13 @@ bool isColumn(const std::wstring& columnName, _UINT32 listIndex, _UINT16& indexC if(arrColumn != XLS::GlobalWorkbookInfo::mapTableColumnNames_static.end()) { indexColumn = -1; + auto unqotedName = columnName; + if(!unqotedName.empty() && unqotedName.at(0) == '\'') + unqotedName = unqotedName.substr(1, unqotedName.size() - 1); for (const auto& itemColumn : arrColumn->second) { ++indexColumn; - if (columnName == itemColumn) + if (unqotedName == itemColumn) { return true; } diff --git a/MsBinaryFile/XlsFile/Format/Logic/GlobalsSubstream.cpp b/MsBinaryFile/XlsFile/Format/Logic/GlobalsSubstream.cpp index 2ff7d550bf..eb8fa5c5da 100644 --- a/MsBinaryFile/XlsFile/Format/Logic/GlobalsSubstream.cpp +++ b/MsBinaryFile/XlsFile/Format/Logic/GlobalsSubstream.cpp @@ -170,7 +170,13 @@ const bool GlobalsSubstream::loadContent(BinProcessor& proc) { CFRecordType::TypeId type = proc.getNextRecordType(); - if (type == rt_NONE) break; + if (type == rt_NONE) + { + proc.SkipRecord(); + type = proc.getNextRecordType(); + if (type == rt_NONE) + break; + } if (type == rt_EOF) { proc.mandatory(); diff --git a/OOXML/Base/Unit.cpp b/OOXML/Base/Unit.cpp index c4105c4dfc..bbd808e890 100644 --- a/OOXML/Base/Unit.cpp +++ b/OOXML/Base/Unit.cpp @@ -570,7 +570,26 @@ namespace XmlUtils } unsigned int GetUInteger(const std::wstring& string) { - return (unsigned int)GetInteger(string); + if (string.empty()) return 0; + + unsigned int iVal = 0; + try + { + iVal = std::stod(string); + } + catch(...) + { + try + { + iVal = std::wcstoll(string.c_str(), NULL, 10); + } + catch(...) + { + return 0; + } + } + + return iVal; } double GetDouble(const std::wstring& string) { diff --git a/OOXML/Binary/Document/BinReader/Readers.cpp b/OOXML/Binary/Document/BinReader/Readers.cpp index 689c0ea7ad..9d56fa52fd 100644 --- a/OOXML/Binary/Document/BinReader/Readers.cpp +++ b/OOXML/Binary/Document/BinReader/Readers.cpp @@ -35,8 +35,6 @@ #include "../BinWriter/BinReaderWriterDefines.h" #include "../../Sheets/Writer/BinaryReader.h" -#include "../../../PPTXFormat/App.h" -#include "../../../PPTXFormat/Core.h" #include "../../../PPTXFormat/Logic/HeadingVariant.h" #include "../../../DocxFormat/Settings/Settings.h" @@ -10200,20 +10198,16 @@ int BinaryFileReader::ReadMainTable() // break; case c_oSerTableTypes::App: { - PPTX::App oApp(NULL); - oApp.fromPPTY(&m_oBufferedStream); OOX::CApp* pApp = new OOX::CApp(NULL); - pApp->FromPptxApp(&oApp); + pApp->fromPPTY(&m_oBufferedStream); pApp->SetRequiredDefaults(); m_oFileWriter.m_pApp = pApp; } break; case c_oSerTableTypes::Core: { - PPTX::Core oCore(NULL); - oCore.fromPPTY(&m_oBufferedStream); OOX::CCore* pCore = new OOX::CCore(NULL); - pCore->FromPptxCore(&oCore); + pCore->fromPPTY(&m_oBufferedStream); pCore->SetRequiredDefaults(); m_oFileWriter.m_pCore = pCore; } diff --git a/OOXML/Binary/Document/BinWriter/BinWriters.cpp b/OOXML/Binary/Document/BinWriter/BinWriters.cpp index 2599d73734..9028b19b3a 100644 --- a/OOXML/Binary/Document/BinWriter/BinWriters.cpp +++ b/OOXML/Binary/Document/BinWriter/BinWriters.cpp @@ -36,8 +36,6 @@ #include "../../../../Common/OfficeFileFormatChecker.h" #include "../../Presentation/FontCutter.h" -#include "../../../PPTXFormat/App.h" -#include "../../../PPTXFormat/Core.h" #include "../../../PPTXFormat/Logic/HeadingVariant.h" #include "../../Sheets/Reader/BinaryWriter.h" #include "BinEquationWriter.h" @@ -9653,18 +9651,14 @@ void BinaryFileWriter::intoBindoc(const std::wstring& sSrcPath) if ((pDocx) && (pDocx->m_pApp)) { nCurPos = this->WriteTableStart(BinDocxRW::c_oSerTableTypes::App); - PPTX::App* pAppTmp = pDocx->m_pApp->ToPptxApp(); - pAppTmp->toPPTY(&oBufferedStream); - delete pAppTmp; + pDocx->m_pApp->toPPTY(&oBufferedStream); this->WriteTableEnd(nCurPos); } if ((pDocx) && (pDocx->m_pCore)) { nCurPos = this->WriteTableStart(BinDocxRW::c_oSerTableTypes::Core); - PPTX::Core* pCoreTmp = pDocx->m_pCore->ToPptxCore(); - pCoreTmp->toPPTY(&oBufferedStream); - delete pCoreTmp; + pDocx->m_pCore->toPPTY(&oBufferedStream); this->WriteTableEnd(nCurPos); } if (NULL != m_oParamsWriter.m_pTheme) diff --git a/OOXML/Binary/Presentation/Converter.cpp b/OOXML/Binary/Presentation/Converter.cpp index 9d7698deec..e63dbeecea 100644 --- a/OOXML/Binary/Presentation/Converter.cpp +++ b/OOXML/Binary/Presentation/Converter.cpp @@ -254,7 +254,7 @@ namespace PPTX2EditorAdvanced oBinaryWriter.WriteULONG(0); // App - smart_ptr app = oFolder.Get(OOX::FileTypes::App).smart_dynamic_cast(); + smart_ptr app = oFolder.Get(OOX::FileTypes::App).smart_dynamic_cast(); if (app.is_init()) { oBinaryWriter.StartMainRecord(NSBinPptxRW::NSMainTables::App); @@ -262,7 +262,7 @@ namespace PPTX2EditorAdvanced } // Core - smart_ptr core = oFolder.Get(OOX::FileTypes::Core).smart_dynamic_cast(); + smart_ptr core = oFolder.Get(OOX::FileTypes::Core).smart_dynamic_cast(); if (core.is_init()) { oBinaryWriter.StartMainRecord(NSBinPptxRW::NSMainTables::Core); diff --git a/OOXML/Binary/Presentation/PPTXWriter.cpp b/OOXML/Binary/Presentation/PPTXWriter.cpp index 47d45c37b0..27a937c557 100644 --- a/OOXML/Binary/Presentation/PPTXWriter.cpp +++ b/OOXML/Binary/Presentation/PPTXWriter.cpp @@ -1109,7 +1109,7 @@ namespace NSBinPptxRW } void CPPTXWriter::SetRequiredDefaultsApp() { - m_oApp.AppVersion.reset(NULL); + m_oApp.m_sAppVersion.reset(NULL); std::wstring sApplication = NSSystemUtils::GetEnvVariable(NSSystemUtils::gc_EnvApplicationName); if (sApplication.empty()) sApplication = NSSystemUtils::gc_EnvApplicationNameDefault; @@ -1117,20 +1117,20 @@ namespace NSBinPptxRW std::string s = VALUE2STR(INTVER); sApplication += L"/" + std::wstring(s.begin(), s.end()); #endif - m_oApp.Application = sApplication; + m_oApp.m_sApplication = sApplication; } void CPPTXWriter::CreateDefaultApp() { - m_oApp.TotalTime = 0; - m_oApp.Words = 0; + m_oApp.m_nTotalTime = 0; + m_oApp.m_nWords = 0; SetRequiredDefaultsApp(); - m_oApp.PresentationFormat = L"On-screen Show (4:3)"; - m_oApp.Paragraphs = 0; - m_oApp.Slides = (int)m_arSlides.size(); - m_oApp.Notes = (int)m_arSlides.size(); - m_oApp.HiddenSlides = 0; - m_oApp.MMClips = 2; - m_oApp.ScaleCrop = false; + m_oApp.m_sPresentationForm = L"On-screen Show (4:3)"; + m_oApp.m_nParagraphs = 0; + m_oApp.m_nSlides = (int)m_arSlides.size(); + m_oApp.m_nNotes = (int)m_arSlides.size(); + m_oApp.m_nHiddenSlides = 0; + m_oApp.m_nMMClips = 2; + m_oApp.m_bScaleCrop = false; int nCountThemes = (int)m_arSlideMasters.size(); int nCountSlides = (int)m_arSlides.size(); @@ -1162,35 +1162,35 @@ namespace NSBinPptxRW m_oApp.TitlesOfParts[nCountThemes + i].m_title = s; } - m_oApp.LinksUpToDate = false; - m_oApp.SharedDoc = false; - m_oApp.HyperlinksChanged = false; + m_oApp.m_bLinksUpToDate = false; + m_oApp.m_bSharedDoc = false; + m_oApp.m_bHyperlinksChanged = false; } void CPPTXWriter::SetRequiredDefaultsCore() { - if (!m_oCore.creator.IsInit()) + if (!m_oCore.m_sCreator.IsInit()) { std::wstring sCreator = NSSystemUtils::GetEnvVariable(NSSystemUtils::gc_EnvCreator); if (!sCreator.empty()) - m_oCore.creator = sCreator; + m_oCore.m_sCreator = sCreator; } - if (!m_oCore.created.IsInit()) + if (!m_oCore.m_sCreated.IsInit()) { std::wstring sCreated = NSSystemUtils::GetEnvVariable(NSSystemUtils::gc_EnvCreated); if (!sCreated.empty()) - m_oCore.created = sCreated; + m_oCore.m_sCreated = sCreated; } std::wstring sLastModifiedBy = NSSystemUtils::GetEnvVariable(NSSystemUtils::gc_EnvLastModifiedBy); if (!sLastModifiedBy.empty()) - m_oCore.lastModifiedBy = sLastModifiedBy; + m_oCore.m_sLastModifiedBy = sLastModifiedBy; std::wstring sModified = NSSystemUtils::GetEnvVariable(NSSystemUtils::gc_EnvModified); if (!sModified.empty()) - m_oCore.modified = sModified; + m_oCore.m_sModified = sModified; } void CPPTXWriter::CreateDefaultCore() { // m_oCore.creator = _T(""); - m_oCore.lastModifiedBy = _T(""); + m_oCore.m_sLastModifiedBy = _T(""); } void CPPTXWriter::CreateDefaultViewProps() { diff --git a/OOXML/Binary/Presentation/PPTXWriter.h b/OOXML/Binary/Presentation/PPTXWriter.h index b14c951cfa..02429183f9 100644 --- a/OOXML/Binary/Presentation/PPTXWriter.h +++ b/OOXML/Binary/Presentation/PPTXWriter.h @@ -72,8 +72,8 @@ namespace NSBinPptxRW PPTX::Presentation m_oPresentation; PPTX::TableStyles m_oTableStyles; OOX::CVmlDrawing m_oVmlDrawing; - PPTX::App m_oApp; - PPTX::Core m_oCore; + OOX::CApp m_oApp; + OOX::CCore m_oCore; nullable m_oCustomProperties; PPTX::ViewProps m_oViewProps; PPTX::PresProps m_oPresProps; diff --git a/OOXML/Binary/Sheets/Reader/BinaryWriter.cpp b/OOXML/Binary/Sheets/Reader/BinaryWriter.cpp index bb746eede8..311c7c7d1b 100644 --- a/OOXML/Binary/Sheets/Reader/BinaryWriter.cpp +++ b/OOXML/Binary/Sheets/Reader/BinaryWriter.cpp @@ -38,8 +38,6 @@ #include "../../../../Common/OfficeFileErrorDescription.h" #include "../../Presentation/FontCutter.h" -#include "../../../PPTXFormat/App.h" -#include "../../../PPTXFormat/Core.h" #include "../../../PPTXFormat/Logic/HeadingVariant.h" #include "../../../XlsxFormat/Xlsx.h" @@ -8777,14 +8775,14 @@ void BinaryFileWriter::WriteContent(OOX::Document *pDocument, NSFontCutter::CEmb if(pXlsx && pXlsx->m_pApp) { nCurPos = this->WriteTableStart(c_oSerTableTypes::App); - pXlsx->m_pApp->ToPptxApp()->toPPTY(&m_oBcw->m_oStream); + pXlsx->m_pApp->toPPTY(&m_oBcw->m_oStream); this->WriteTableEnd(nCurPos); } if(pXlsx && pXlsx->m_pCore) { nCurPos = this->WriteTableStart(c_oSerTableTypes::Core); - pXlsx->m_pCore->ToPptxCore()->toPPTY(&m_oBcw->m_oStream); + pXlsx->m_pCore->toPPTY(&m_oBcw->m_oStream); this->WriteTableEnd(nCurPos); } diff --git a/OOXML/Binary/Sheets/Writer/BinaryReader.cpp b/OOXML/Binary/Sheets/Writer/BinaryReader.cpp index bd4047514f..0e94b1be81 100644 --- a/OOXML/Binary/Sheets/Writer/BinaryReader.cpp +++ b/OOXML/Binary/Sheets/Writer/BinaryReader.cpp @@ -47,8 +47,6 @@ #include "../../../PPTXFormat/Theme.h" #include "../../../../MsBinaryFile/Common/Vml/toVmlConvert.h" -#include "../../../PPTXFormat/App.h" -#include "../../../PPTXFormat/Core.h" #include "../../../PPTXFormat/Logic/HeadingVariant.h" #include "../../../PPTXFormat/Logic/Shape.h" @@ -8864,11 +8862,8 @@ int BinaryFileReader::ReadMainTable(OOX::Spreadsheet::CXlsx& oXlsx, NSBinPptxRW: { case c_oSerTableTypes::App: { - PPTX::App oApp(NULL); - oApp.fromPPTY(&oBufferedStream); - OOX::CApp* pApp = new OOX::CApp(NULL); - pApp->FromPptxApp(&oApp); + pApp->fromPPTY(&oBufferedStream); pApp->SetRequiredDefaults(); oXlsx.m_pApp = pApp; smart_ptr oCurFile(pApp); @@ -8876,11 +8871,8 @@ int BinaryFileReader::ReadMainTable(OOX::Spreadsheet::CXlsx& oXlsx, NSBinPptxRW: }break; case c_oSerTableTypes::Core: { - PPTX::Core oCore(NULL); - oCore.fromPPTY(&oBufferedStream); - OOX::CCore* pCore = new OOX::CCore(NULL); - pCore->FromPptxCore(&oCore); + pCore->fromPPTY(&oBufferedStream); pCore->SetRequiredDefaults(); oXlsx.m_pCore = pCore; smart_ptr oCurFile(pCore); diff --git a/OOXML/Binary/Sheets/Writer/CSVWriter.cpp b/OOXML/Binary/Sheets/Writer/CSVWriter.cpp index 46bcffdc06..ea7518827c 100644 --- a/OOXML/Binary/Sheets/Writer/CSVWriter.cpp +++ b/OOXML/Binary/Sheets/Writer/CSVWriter.cpp @@ -731,7 +731,12 @@ void CSVWriter::Impl::WriteCell(OOX::Spreadsheet::CCell *pCell) //} //else bool bString = false; - if (pCell->m_oValue.IsInit()) + + if (pCell->m_oFormula.IsInit()) + { + sCellValue = pCell->m_oFormula->m_sText; + } + else if (pCell->m_oValue.IsInit()) { sCellValue = pCell->m_oValue->ToString(); @@ -796,10 +801,7 @@ void CSVWriter::Impl::WriteCell(OOX::Spreadsheet::CCell *pCell) } } - else if (pCell->m_oFormula.IsInit()) - { - sCellValue = pCell->m_oFormula->m_sText; - } + // Escape cell value if (m_bJSON) diff --git a/OOXML/Common/SimpleTypes_Shared.cpp b/OOXML/Common/SimpleTypes_Shared.cpp index ba172acf45..8b13bbfbad 100644 --- a/OOXML/Common/SimpleTypes_Shared.cpp +++ b/OOXML/Common/SimpleTypes_Shared.cpp @@ -722,7 +722,7 @@ namespace SimpleTypes { try { - this->m_eValue = XmlUtils::GetInteger(sValue); + this->m_eValue = XmlUtils::GetUInteger(sValue); return this->m_eValue; } catch(...) diff --git a/OOXML/Common/SimpleTypes_Vml.h b/OOXML/Common/SimpleTypes_Vml.h index 9d4bdba44e..7f8eaaeea8 100644 --- a/OOXML/Common/SimpleTypes_Vml.h +++ b/OOXML/Common/SimpleTypes_Vml.h @@ -1503,9 +1503,8 @@ namespace SimpleTypes SimpleTypes_DefaultString(CVml_Vector2D_Units) - private: - - double m_dX; // В пунктах + private: + double m_dX; // В пунктах double m_dY; // В пунктах }; @@ -1529,7 +1528,7 @@ namespace SimpleTypes SimpleTypes_DefaultString(CVml_Vector2D_Percentage) - private: + private: double m_dX; // double m_dY; // }; @@ -1554,8 +1553,8 @@ namespace SimpleTypes SimpleTypes_DefaultString(CVml_Vector2D_1_65536) - private: - double m_dX; // + private: + double m_dX; // double m_dY; // }; @@ -1639,8 +1638,8 @@ namespace SimpleTypes std::wstring m_sIdX; // Значение для типа Formula иди AdjValue std::wstring m_sIdY; // - double m_dX; // Значение для типа Constant - double m_dY; // + double m_dX; // Значение для типа Constant + double m_dY; // }; //-------------------------------------------------------------------------------- @@ -1788,8 +1787,8 @@ namespace SimpleTypes SimpleTypes_DefaultString(CVml_TextBoxInset) - private: - double m_dLeft; + private: + double m_dLeft; double m_dTop; double m_dRight; double m_dBottom; diff --git a/OOXML/Common/SimpleTypes_Word.cpp b/OOXML/Common/SimpleTypes_Word.cpp index 9f8c41aba0..2233a9926f 100644 --- a/OOXML/Common/SimpleTypes_Word.cpp +++ b/OOXML/Common/SimpleTypes_Word.cpp @@ -4689,16 +4689,17 @@ namespace SimpleTypes ECryptAlgoritmName CCryptAlgoritmName::FromString(const std::wstring &sValue) { - if ( L"MD2" == sValue || L"1" == sValue ) this->m_eValue = cryptalgoritmnameMD2; - else if ( L"MD4" == sValue || L"2" == sValue ) this->m_eValue = cryptalgoritmnameMD4; - else if ( L"MD5" == sValue || L"3" == sValue ) this->m_eValue = cryptalgoritmnameMD5; - else if ( L"RIPEMD-128" == sValue || L"6" == sValue ) this->m_eValue = cryptalgoritmnameRIPEMD128; - else if ( L"RIPEMD-160" == sValue || L"7" == sValue ) this->m_eValue = cryptalgoritmnameRIPEMD160; - else if ( L"SHA-1" == sValue || L"4" == sValue ) this->m_eValue = cryptalgoritmnameSHA1; - else if ( L"SHA-256" == sValue || L"12" == sValue ) this->m_eValue = cryptalgoritmnameSHA256; - else if ( L"SHA-384" == sValue || L"13" == sValue ) this->m_eValue = cryptalgoritmnameSHA384; - else if ( L"SHA-512" == sValue || L"14" == sValue ) this->m_eValue = cryptalgoritmnameSHA512; - else if ( L"WHIRLPOOL" == sValue ) this->m_eValue = cryptalgoritmnameWHIRLPOOL; + if (L"MD2" == sValue || L"1" == sValue) this->m_eValue = cryptalgoritmnameMD2; + else if (L"MD4" == sValue || L"2" == sValue) this->m_eValue = cryptalgoritmnameMD4; + else if (L"MD5" == sValue || L"3" == sValue) this->m_eValue = cryptalgoritmnameMD5; + else if (L"RIPEMD-128" == sValue || L"6" == sValue) this->m_eValue = cryptalgoritmnameRIPEMD128; + else if (L"RIPEMD-160" == sValue || L"7" == sValue) this->m_eValue = cryptalgoritmnameRIPEMD160; + else if (L"SHA-1" == sValue || L"4" == sValue) this->m_eValue = cryptalgoritmnameSHA1; + else if (L"SHA-256" == sValue || L"12" == sValue) this->m_eValue = cryptalgoritmnameSHA256; + else if (L"SHA-384" == sValue || L"13" == sValue) this->m_eValue = cryptalgoritmnameSHA384; + else if (L"SHA-512" == sValue || L"14" == sValue) this->m_eValue = cryptalgoritmnameSHA512; + else if (L"WHIRLPOOL" == sValue) this->m_eValue = cryptalgoritmnameWHIRLPOOL; + else if (L"PBKDF2" == sValue) this->m_eValue = cryptalgoritmnamePBKDF2; else this->m_eValue = cryptalgoritmnameUnknown; @@ -4719,6 +4720,7 @@ namespace SimpleTypes case cryptalgoritmnameSHA384 : return (L"SHA-384"); case cryptalgoritmnameSHA512 : return (L"SHA-512"); case cryptalgoritmnameWHIRLPOOL : return (L"WHIRLPOOL"); + case cryptalgoritmnamePBKDF2 : return (L"PBKDF2"); default : return (L""); } } diff --git a/OOXML/Common/SimpleTypes_Word.h b/OOXML/Common/SimpleTypes_Word.h index 298711d43b..e882f73610 100644 --- a/OOXML/Common/SimpleTypes_Word.h +++ b/OOXML/Common/SimpleTypes_Word.h @@ -2114,6 +2114,7 @@ namespace SimpleTypes cryptalgoritmnameSHA384 = 8, cryptalgoritmnameSHA512 = 9, cryptalgoritmnameWHIRLPOOL = 10, + cryptalgoritmnamePBKDF2 = 11 }; DEFINE_SIMPLE_TYPE(CCryptAlgoritmName, ECryptAlgoritmName, cryptalgoritmnameUnknown) diff --git a/OOXML/DocxFormat/App.cpp b/OOXML/DocxFormat/App.cpp index d2fe46c880..bf0440af27 100644 --- a/OOXML/DocxFormat/App.cpp +++ b/OOXML/DocxFormat/App.cpp @@ -32,9 +32,9 @@ #include "App.h" #include "Docx.h" #include "../XlsxFormat/Xlsx.h" -#include "../PPTXFormat/App.h" #include "../Common/SimpleTypes_Word.h" #include "../../DesktopEditor/common/SystemUtils.h" +#include "../../DesktopEditor/xml/include/xmlutils.h" namespace OOX { @@ -57,106 +57,6 @@ namespace OOX CApp::~CApp() { } - PPTX::App* CApp::ToPptxApp() - { - PPTX::App* res = new PPTX::App(NULL); - if(m_sTemplate.IsInit()) - res->Template = m_sTemplate.get(); - if(m_nTotalTime.IsInit()) - res->TotalTime = m_nTotalTime.get(); - if(m_nWords.IsInit()) - res->Words = m_nWords.get(); - if(m_sApplication.IsInit()) - res->Application = m_sApplication.get(); - if(m_sPresentationForm.IsInit()) - res->PresentationFormat = m_sPresentationForm.get(); - if(m_nParagraphs.IsInit()) - res->Paragraphs = m_nParagraphs.get(); - if(m_nSlides.IsInit()) - res->Slides = m_nSlides.get(); - if(m_nNotes.IsInit()) - res->Notes = m_nNotes.get(); - if(m_nHiddenSlides.IsInit()) - res->HiddenSlides = m_nHiddenSlides.get(); - if(m_nMMClips.IsInit()) - res->MMClips = m_nMMClips.get(); - if(m_bScaleCrop.IsInit()) - res->ScaleCrop = m_bScaleCrop.get(); - if(m_sCompany.IsInit()) - res->Company = m_sCompany.get(); - if(m_bLinksUpToDate.IsInit()) - res->LinksUpToDate = m_bLinksUpToDate.get(); - if(m_bSharedDoc.IsInit()) - res->SharedDoc = m_bSharedDoc.get(); - if(m_bHyperlinksChanged.IsInit()) - res->HyperlinksChanged = m_bHyperlinksChanged.get(); - if(m_sAppVersion.IsInit()) - res->AppVersion = m_sAppVersion.get(); - if(m_nCharacters.IsInit()) - res->Characters = m_nCharacters.get(); - if(m_nCharactersWithSpaces.IsInit()) - res->CharactersWithSpaces = m_nCharactersWithSpaces.get(); - if(m_nDocSecurity.IsInit()) - res->DocSecurity = m_nDocSecurity.get(); - if(m_sHyperlinkBase.IsInit()) - res->HyperlinkBase = m_sHyperlinkBase.get(); - if(m_nLines.IsInit()) - res->Lines = m_nLines.get(); - if(m_sManager.IsInit()) - res->Manager = m_sManager.get(); - if(m_nPages.IsInit()) - res->Pages = m_nPages.get(); - return res; - } - void CApp::FromPptxApp(PPTX::App* pApp) - { - if(pApp->Template.IsInit()) - m_sTemplate = pApp->Template.get(); - if(pApp->TotalTime.IsInit()) - m_nTotalTime = pApp->TotalTime.get(); - if(pApp->Words.IsInit()) - m_nWords = pApp->Words.get(); - if(pApp->Application.IsInit()) - m_sApplication = pApp->Application.get(); - if(pApp->PresentationFormat.IsInit()) - m_sPresentationForm = pApp->PresentationFormat.get(); - if(pApp->Paragraphs.IsInit()) - m_nParagraphs = pApp->Paragraphs.get(); - if(pApp->Slides.IsInit()) - m_nSlides = pApp->Slides.get(); - if(pApp->Notes.IsInit()) - m_nNotes = pApp->Notes.get(); - if(pApp->HiddenSlides.IsInit()) - m_nHiddenSlides = pApp->HiddenSlides.get(); - if(pApp->MMClips.IsInit()) - m_nMMClips = pApp->MMClips.get(); - if(pApp->ScaleCrop.IsInit()) - m_bScaleCrop = pApp->ScaleCrop.get(); - if(pApp->Company.IsInit()) - m_sCompany = pApp->Company.get(); - if(pApp->LinksUpToDate.IsInit()) - m_bLinksUpToDate = pApp->LinksUpToDate.get(); - if(pApp->SharedDoc.IsInit()) - m_bSharedDoc = pApp->SharedDoc.get(); - if(pApp->HyperlinksChanged.IsInit()) - m_bHyperlinksChanged = pApp->HyperlinksChanged.get(); - if(pApp->AppVersion.IsInit()) - m_sAppVersion = pApp->AppVersion.get(); - if(pApp->Characters.IsInit()) - m_nCharacters = pApp->Characters.get(); - if(pApp->CharactersWithSpaces.IsInit()) - m_nCharactersWithSpaces = pApp->CharactersWithSpaces.get(); - if(pApp->DocSecurity.IsInit()) - m_nDocSecurity = pApp->DocSecurity.get(); - if(pApp->HyperlinkBase.IsInit()) - m_sHyperlinkBase = pApp->HyperlinkBase.get(); - if(pApp->Lines.IsInit()) - m_nLines = pApp->Lines.get(); - if(pApp->Manager.IsInit()) - m_sManager = pApp->Manager.get(); - if(pApp->Pages.IsInit()) - m_nPages = pApp->Pages.get(); - } void CApp::read(const CPath& oPath) { XmlUtils::CXmlNode oProperties; @@ -231,6 +131,22 @@ namespace OOX if ( oProperties.GetNode( _T("Words"), oItem ) ) m_nWords = oItem.GetText(); + + XmlUtils::CXmlNode oHP = oProperties.ReadNode(_T("HeadingPairs")); + XmlUtils::CXmlNode oNodeVector1; + if (oHP.GetNode(_T("vt:vector"), oNodeVector1)) + { + XmlMacroReadAttributeBase(oNodeVector1, _T("size"), m_Headings); + XmlMacroLoadArray(oNodeVector1, _T("vt:variant"), HeadingPairs, PPTX::Logic::HeadingVariant); + } + + XmlUtils::CXmlNode oTP = oProperties.ReadNode(_T("TitlesOfParts")); + XmlUtils::CXmlNode oNodeVector2; + if (oTP.GetNode(_T("vt:vector"), oNodeVector2)) + { + XmlMacroReadAttributeBase(oNodeVector2, _T("size"), m_VectorSize); + XmlMacroLoadArray(oNodeVector2, _T("vt:variant"), TitlesOfParts, PPTX::Logic::PartTitle); + } } } void CApp::write(const CPath& oPath, const CPath& oDirectory, CContentTypes& oContent) const @@ -238,169 +154,10 @@ namespace OOX std::wstring sXml; sXml = _T(""); - if ( m_sApplication.IsInit() ) - { - sXml += _T(""); - sXml += XmlUtils::EncodeXmlString(m_sApplication.get()); - if ( m_sAppVersion.IsInit() ) - { - sXml += L"/"; - sXml += XmlUtils::EncodeXmlString(m_sAppVersion.get()); - } - sXml += _T(""); - } + NSBinPptxRW::CXmlWriter oWriter; + toXmlWriter(&oWriter); - //if ( m_sAppVersion.IsInit() ) - only for ms editors versions - //{ - // sXml += _T(""); - // sXml += m_sAppVersion.get(); // error in ms editors - "2.4.510.0" - // sXml += _T(""); - //} - - if ( m_nCharacters.IsInit() ) - { - sXml += _T(""); - sXml += std::to_wstring(*m_nCharacters); - sXml += _T(""); - } - - if ( m_nCharactersWithSpaces.IsInit() ) - { - sXml += _T(""); - sXml += std::to_wstring(*m_nCharactersWithSpaces); - sXml += _T(""); - } - - if ( m_sCompany.IsInit() ) - { - sXml += _T(""); - sXml += XmlUtils::EncodeXmlString(m_sCompany.get()); - sXml += _T(""); - } - - if ( m_nDocSecurity.IsInit() ) - { - sXml += _T(""); - sXml += std::to_wstring(*m_nDocSecurity); - sXml += _T(""); - } - - if ( m_nHiddenSlides.IsInit() ) - { - sXml += _T(""); - sXml += std::to_wstring(*m_nHiddenSlides); - sXml += _T(""); - } - - if ( m_sHyperlinkBase.IsInit() ) - { - sXml += _T(""); - sXml += XmlUtils::EncodeXmlString(m_sHyperlinkBase.get()); - sXml += _T(""); - } - - if ( m_bHyperlinksChanged.IsInit() ) - { - sXml += _T(""); - sXml += *m_bHyperlinksChanged ? L"true" : L"false"; - sXml += _T(""); - } - - if ( m_nLines.IsInit() ) - { - sXml += _T(""); - sXml += std::to_wstring(*m_nLines); - sXml += _T(""); - } - - if ( m_bLinksUpToDate.IsInit() ) - { - sXml += _T(""); - sXml += *m_bLinksUpToDate ? L"true" : L"false";; - sXml += _T(""); - } - - if ( m_sManager.IsInit() ) - { - sXml += _T(""); - sXml += XmlUtils::EncodeXmlString(m_sManager.get()); - sXml += _T(""); - } - - if ( m_nMMClips.IsInit() ) - { - sXml += _T(""); - sXml += std::to_wstring(*m_nMMClips); - sXml += _T(""); - } - - if ( m_nNotes.IsInit() ) - { - sXml += _T(""); - sXml += std::to_wstring(*m_nNotes); - sXml += _T(""); - } - - if ( m_nPages.IsInit() ) - { - sXml += _T(""); - sXml += std::to_wstring(*m_nPages); - sXml += _T(""); - } - - if ( m_nParagraphs.IsInit() ) - { - sXml += _T(""); - sXml += std::to_wstring(*m_nParagraphs); - sXml += _T(""); - } - - if ( m_bScaleCrop.IsInit() ) - { - sXml += _T(""); - sXml += *m_bScaleCrop ? L"true" : L"false";; - sXml += _T(""); - } - - if ( m_bSharedDoc.IsInit() ) - { - sXml += _T(""); - sXml += *m_bSharedDoc ? L"true" : L"false";; - sXml += _T(""); - } - - if ( m_nSlides.IsInit() ) - { - SimpleTypes::CDecimalNumber oNum; - oNum.SetValue( m_nSlides.get() ); - - sXml += _T(""); - sXml += std::to_wstring(*m_nSlides); - sXml += _T(""); - } - - if ( m_sTemplate.IsInit() ) - { - sXml += _T(""); - } - - if ( m_nTotalTime.IsInit() ) - { - sXml += _T(""); - sXml += std::to_wstring(*m_nTotalTime); - sXml += _T(""); - } - - if ( m_nWords.IsInit() ) - { - sXml += _T(""); - sXml += std::to_wstring(*m_nWords); - sXml += _T(""); - } - - sXml += _T(""); + sXml += oWriter.GetXmlString(); NSFile::CFileBinary::SaveToFile( oPath.GetPath(), sXml ); oContent.Registration( type().OverrideType(), oDirectory, oPath.GetFilename() ); @@ -440,4 +197,191 @@ namespace OOX m_sApplication = sApplication; } + void CApp::toPPTY(NSBinPptxRW::CBinaryFileWriter* pWriter) const + { + pWriter->StartRecord(NSBinPptxRW::NSMainTables::App); + + pWriter->WriteBYTE(NSBinPptxRW::g_nodeAttributeStart); + + pWriter->WriteString2(0, m_sTemplate); + pWriter->WriteString2(1, m_sApplication); + pWriter->WriteString2(2, m_sPresentationForm); + pWriter->WriteString2(3, m_sCompany); + pWriter->WriteString2(4, m_sAppVersion); + + pWriter->WriteInt2(5, m_nTotalTime); + pWriter->WriteInt2(6, m_nWords); + pWriter->WriteInt2(7, m_nParagraphs); + pWriter->WriteInt2(8, m_nSlides); + pWriter->WriteInt2(9, m_nNotes); + pWriter->WriteInt2(10, m_nHiddenSlides); + pWriter->WriteInt2(11, m_nMMClips); + + pWriter->WriteBool2(12, m_bScaleCrop); + pWriter->WriteBool2(13, m_bLinksUpToDate); + pWriter->WriteBool2(14, m_bSharedDoc); + pWriter->WriteBool2(15, m_bHyperlinksChanged); + + pWriter->WriteBYTE(NSBinPptxRW::g_nodeAttributeEnd); + + //start new record because new attributes is incompatible with previous versions + pWriter->StartRecord(0); + pWriter->WriteBYTE(NSBinPptxRW::g_nodeAttributeStart); + + pWriter->WriteInt2(16, m_nCharacters); + pWriter->WriteInt2(17, m_nCharactersWithSpaces); + pWriter->WriteInt2(18, m_nDocSecurity); + pWriter->WriteString2(19, m_sHyperlinkBase); + pWriter->WriteInt2(20, m_nLines); + pWriter->WriteString2(21, m_sManager); + pWriter->WriteInt2(22, m_nPages); + + pWriter->WriteBYTE(NSBinPptxRW::g_nodeAttributeEnd); + pWriter->EndRecord(); + + pWriter->EndRecord(); + } + void CApp::fromPPTY(NSBinPptxRW::CBinaryFileReader* pReader) + { + pReader->Skip(1); // type + LONG _end_rec = pReader->GetPos() + pReader->GetRecordSize() + 4; + + pReader->Skip(1); // start attributes + + while (true) + { + BYTE _at = pReader->GetUChar_TypeNode(); + if (_at == NSBinPptxRW::g_nodeAttributeEnd) + break; + + switch (_at) + { + case 0: m_sTemplate = pReader->GetString2(); break; + case 1: m_sApplication = pReader->GetString2(); break; + case 2: m_sPresentationForm = pReader->GetString2(); break; + case 3: m_sCompany = pReader->GetString2(); break; + case 4: m_sAppVersion = pReader->GetString2(); break; + case 5: m_nTotalTime = pReader->GetULong(); break; + case 6: m_nWords = pReader->GetULong(); break; + case 7: m_nParagraphs = pReader->GetULong(); break; + case 8: m_nSlides = pReader->GetULong(); break; + case 9: m_nNotes = pReader->GetULong(); break; + case 10: m_nHiddenSlides = pReader->GetULong(); break; + case 11: m_nMMClips = pReader->GetULong(); break; + case 12: m_bScaleCrop = pReader->GetBool(); break; + case 13: m_bLinksUpToDate = pReader->GetBool(); break; + case 14: m_bSharedDoc = pReader->GetBool(); break; + case 15: m_bHyperlinksChanged = pReader->GetBool(); break; + default: break; + } + } + while (pReader->GetPos() < _end_rec) + { + BYTE _at = pReader->GetUChar(); + switch (_at) + { + case 0: + { + LONG _end_rec2 = pReader->GetPos() + pReader->GetRecordSize() + 4; + + pReader->Skip(1); // start attributes + + while (true) + { + BYTE _at = pReader->GetUChar_TypeNode(); + if (_at == NSBinPptxRW::g_nodeAttributeEnd) + break; + + switch (_at) + { + case 16: m_nCharacters = pReader->GetULong(); break; + case 17: m_nCharactersWithSpaces = pReader->GetULong(); break; + case 18: m_nDocSecurity = pReader->GetULong(); break; + case 19: m_sHyperlinkBase = pReader->GetString2(); break; + case 20: m_nLines = pReader->GetULong(); break; + case 21: m_sManager = pReader->GetString2(); break; + case 22: m_nPages = pReader->GetULong(); break; + default: break; + } + } + + pReader->Seek(_end_rec2); + } + break; + default: + { + pReader->SkipRecord(); + break; + } + } + } + + pReader->Seek(_end_rec); + } + void CApp::toXmlWriter(NSBinPptxRW::CXmlWriter* pWriter) const + { + pWriter->StartNode(_T("Properties")); + + pWriter->StartAttributes(); + + pWriter->WriteAttribute(_T("xmlns"), PPTX::g_Namespaces.xmlns.m_strLink); + pWriter->WriteAttribute(_T("xmlns:vt"), PPTX::g_Namespaces.vt.m_strLink); + + pWriter->EndAttributes(); + + pWriter->WriteNodeValue2(_T("Template"), m_sTemplate); + pWriter->WriteNodeValue(_T("TotalTime"), m_nTotalTime); + pWriter->WriteNodeValue(_T("Pages"), m_nPages); + pWriter->WriteNodeValue(_T("Words"), m_nWords); + pWriter->WriteNodeValue(_T("Characters"), m_nCharacters); + pWriter->WriteNodeValue(_T("CharactersWithSpaces"), m_nCharactersWithSpaces); + pWriter->WriteNodeValue2(_T("Application"), m_sApplication); + pWriter->WriteNodeValue(_T("DocSecurity"), m_nDocSecurity); + pWriter->WriteNodeValue2(_T("PresentationFormat"), m_sPresentationForm); + pWriter->WriteNodeValue(_T("Lines"), m_nLines); + pWriter->WriteNodeValue(_T("Paragraphs"), m_nParagraphs); + pWriter->WriteNodeValue(_T("Slides"), m_nSlides); + pWriter->WriteNodeValue(_T("Notes"), m_nNotes); + pWriter->WriteNodeValue(_T("HiddenSlides"), m_nHiddenSlides); + pWriter->WriteNodeValue(_T("MMClips"), m_nMMClips); + pWriter->WriteNodeValue(_T("ScaleCrop"), m_bScaleCrop); + + pWriter->StartNode(_T("HeadingPairs")); + pWriter->EndAttributes(); + + pWriter->StartNode(_T("vt:vector")); + pWriter->StartAttributes(); + pWriter->WriteAttribute(_T("size"), (int)HeadingPairs.size()); + pWriter->WriteAttribute(_T("baseType"), (std::wstring)_T("variant")); + pWriter->EndAttributes(); + + pWriter->WriteArray2(HeadingPairs); + + pWriter->EndNode(_T("vt:vector")); + pWriter->EndNode(_T("HeadingPairs")); + + pWriter->StartNode(_T("TitlesOfParts")); + pWriter->EndAttributes(); + + pWriter->StartNode(_T("vt:vector")); + pWriter->StartAttributes(); + pWriter->WriteAttribute(_T("size"), (int)TitlesOfParts.size()); + pWriter->WriteAttribute(_T("baseType"), (std::wstring)_T("lpstr")); + pWriter->EndAttributes(); + + pWriter->WriteArray2(TitlesOfParts); + + pWriter->EndNode(_T("vt:vector")); + pWriter->EndNode(_T("TitlesOfParts")); + + pWriter->WriteNodeValue2(_T("Manager"), m_sManager); + pWriter->WriteNodeValue2(_T("Company"), m_sCompany); + pWriter->WriteNodeValue(_T("LinksUpToDate"), m_bLinksUpToDate); + pWriter->WriteNodeValue(_T("SharedDoc"), m_bSharedDoc); + pWriter->WriteNodeValue2(_T("HyperlinkBase"), m_sHyperlinkBase); + pWriter->WriteNodeValue(_T("HyperlinksChanged"), m_bHyperlinksChanged); + pWriter->WriteNodeValue2(_T("AppVersion"), m_sAppVersion); + + pWriter->EndNode(_T("Properties")); + } } // namespace OOX diff --git a/OOXML/DocxFormat/App.h b/OOXML/DocxFormat/App.h index f844045502..6d36895334 100644 --- a/OOXML/DocxFormat/App.h +++ b/OOXML/DocxFormat/App.h @@ -32,12 +32,12 @@ #pragma once #include "File.h" +#include "WritingElement.h" #include "../Base/Nullable.h" -namespace PPTX -{ - class App; -} +#include "../PPTXFormat/Logic/PartTitle.h" +#include "../PPTXFormat/Logic/HeadingVariant.h" + namespace OOX { class CApp : public OOX::File @@ -58,37 +58,43 @@ namespace OOX void SetDefaults(); void SetRequiredDefaults(); - PPTX::App* ToPptxApp(); - void FromPptxApp(PPTX::App* pApp); + virtual void toPPTY(NSBinPptxRW::CBinaryFileWriter* pWriter) const; + virtual void fromPPTY(NSBinPptxRW::CBinaryFileReader* pReader); + virtual void toXmlWriter(NSBinPptxRW::CXmlWriter* pWriter) const; // TO DO: DigSig - // HeadingPairs // HLinks - // TitlesOfParts - nullable_string m_sApplication; + nullable_string m_sApplication; nullable_string m_sAppVersion; nullable_int m_nCharacters; nullable_int m_nCharactersWithSpaces; - nullable_string m_sCompany; + nullable_string m_sCompany; nullable_int m_nDocSecurity; nullable_int m_nHiddenSlides; - nullable_string m_sHyperlinkBase; + nullable_string m_sHyperlinkBase; nullable_bool m_bHyperlinksChanged; nullable_int m_nLines; nullable_bool m_bLinksUpToDate; - nullable_string m_sManager; + nullable_string m_sManager; nullable_int m_nMMClips; nullable_int m_nNotes; nullable_int m_nPages; nullable_int m_nParagraphs; - nullable_string m_sPresentationForm; + nullable_string m_sPresentationForm; nullable_bool m_bScaleCrop; nullable_bool m_bSharedDoc; nullable_int m_nSlides; - nullable_string m_sTemplate; + nullable_string m_sTemplate; nullable_int m_nTotalTime; nullable_int m_nWords; + + std::vector HeadingPairs; + std::vector TitlesOfParts; + private: + nullable_int m_VectorSize; + nullable_int m_Headings; }; + } // namespace OOX diff --git a/OOXML/DocxFormat/Core.cpp b/OOXML/DocxFormat/Core.cpp index 2b8b76ebbb..24d54078e0 100644 --- a/OOXML/DocxFormat/Core.cpp +++ b/OOXML/DocxFormat/Core.cpp @@ -33,7 +33,6 @@ #include "Core.h" #include "Docx.h" #include "../XlsxFormat/Xlsx.h" -#include "../PPTXFormat/Core.h" #include "../../DesktopEditor/common/SystemUtils.h" @@ -270,73 +269,152 @@ xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"); { m_sLastModifiedBy = sVal; } + void CCore::toPPTY(NSBinPptxRW::CBinaryFileWriter* pWriter) const + { + pWriter->StartRecord(NSBinPptxRW::NSMainTables::Core); - PPTX::Core* CCore::ToPptxCore() - { - PPTX::Core* res = new PPTX::Core(NULL); - if (m_sCategory.IsInit()) - res->category = m_sCategory.get(); - if (m_sContentStatus.IsInit()) - res->contentStatus = m_sContentStatus.get(); - if (m_sCreated.IsInit()) - res->created = m_sCreated.get(); - if (m_sCreator.IsInit()) - res->creator = m_sCreator.get(); - if (m_sDescription.IsInit()) - res->description = m_sDescription.get(); - if (m_sIdentifier.IsInit()) - res->identifier = m_sIdentifier.get(); - if (m_sKeywords.IsInit()) - res->keywords = m_sKeywords.get(); - if (m_sLanguage.IsInit()) - res->language = m_sLanguage.get(); - if (m_sLastModifiedBy.IsInit()) - res->lastModifiedBy = m_sLastModifiedBy.get(); - if (m_sLastPrinted.IsInit()) - res->lastPrinted = m_sLastPrinted.get(); - if (m_sModified.IsInit()) - res->modified = m_sModified.get(); - if (m_sRevision.IsInit()) - res->revision = m_sRevision.get(); - if (m_sSubject.IsInit()) - res->subject = m_sSubject.get(); - if (m_sTitle.IsInit()) - res->title = m_sTitle.get(); - if (m_sVersion.IsInit()) - res->version = m_sVersion.get(); - return res; + pWriter->WriteBYTE(NSBinPptxRW::g_nodeAttributeStart); + + pWriter->WriteString2(0, m_sTitle); + pWriter->WriteString2(1, m_sCreator); + pWriter->WriteString2(2, m_sLastModifiedBy); + pWriter->WriteString2(3, m_sRevision); + pWriter->WriteString2(4, m_sCreated); + pWriter->WriteString2(5, m_sModified); + + pWriter->WriteBYTE(NSBinPptxRW::g_nodeAttributeEnd); + + //start new record because new attributes is incompatible with previous versions + pWriter->StartRecord(0); + pWriter->WriteBYTE(NSBinPptxRW::g_nodeAttributeStart); + + pWriter->WriteString2(6, m_sCategory); + pWriter->WriteString2(7, m_sContentStatus); + pWriter->WriteString2(8, m_sDescription); + pWriter->WriteString2(9, m_sIdentifier); + pWriter->WriteString2(10, m_sKeywords); + pWriter->WriteString2(11, m_sLanguage); + pWriter->WriteString2(12, m_sLastPrinted); + pWriter->WriteString2(13, m_sSubject); + pWriter->WriteString2(14, m_sVersion); + + pWriter->WriteBYTE(NSBinPptxRW::g_nodeAttributeEnd); + pWriter->EndRecord(); + + pWriter->EndRecord(); } - void CCore::FromPptxCore(PPTX::Core* pCore) + void CCore::fromPPTY(NSBinPptxRW::CBinaryFileReader* pReader) { - if(pCore->category.IsInit()) - m_sCategory = pCore->category.get(); - if(pCore->contentStatus.IsInit()) - m_sContentStatus = pCore->contentStatus.get(); - if(pCore->created.IsInit()) - m_sCreated = pCore->created.get(); - if(pCore->creator.IsInit()) - m_sCreator = pCore->creator.get(); - if(pCore->description.IsInit()) - m_sDescription = pCore->description.get(); - if(pCore->identifier.IsInit()) - m_sIdentifier = pCore->identifier.get(); - if(pCore->keywords.IsInit()) - m_sKeywords = pCore->keywords.get(); - if(pCore->language.IsInit()) - m_sLanguage = pCore->language.get(); - if(pCore->lastModifiedBy.IsInit()) - m_sLastModifiedBy = pCore->lastModifiedBy.get(); - if(pCore->lastPrinted.IsInit()) - m_sLastPrinted = pCore->lastPrinted.get(); - if(pCore->modified.IsInit()) - m_sModified = pCore->modified.get(); - if(pCore->revision.IsInit()) - m_sRevision = pCore->revision.get(); - if(pCore->subject.IsInit()) - m_sSubject = pCore->subject.get(); - if(pCore->title.IsInit()) - m_sTitle = pCore->title.get(); - if(pCore->version.IsInit()) - m_sVersion = pCore->version.get(); + pReader->Skip(1); // type + LONG _end_rec = pReader->GetPos() + pReader->GetRecordSize() + 4; + + pReader->Skip(1); // start attributes + + while (true) + { + BYTE _at = pReader->GetUChar_TypeNode(); + if (_at == NSBinPptxRW::g_nodeAttributeEnd) + break; + + switch (_at) + { + case 0: m_sTitle = pReader->GetString2(); break; + case 1: m_sCreator = pReader->GetString2(); break; + case 2: m_sLastModifiedBy = pReader->GetString2(); break; + case 3: m_sRevision = pReader->GetString2(); break; + case 4: m_sCreated = pReader->GetString2(); break; + case 5: m_sModified = pReader->GetString2(); break; + default: break; + } + } + while (pReader->GetPos() < _end_rec) + { + BYTE _at = pReader->GetUChar(); + switch (_at) + { + case 0: + { + LONG _end_rec2 = pReader->GetPos() + pReader->GetRecordSize() + 4; + + pReader->Skip(1); // start attributes + + while (true) + { + BYTE _at = pReader->GetUChar_TypeNode(); + if (_at == NSBinPptxRW::g_nodeAttributeEnd) + break; + + switch (_at) + { + case 6: m_sCategory = pReader->GetString2(); break; + case 7: m_sContentStatus = pReader->GetString2(); break; + case 8: m_sDescription = pReader->GetString2(); break; + case 9: m_sIdentifier = pReader->GetString2(); break; + case 10: m_sKeywords = pReader->GetString2(); break; + case 11: m_sLanguage = pReader->GetString2(); break; + case 12: m_sLastPrinted = pReader->GetString2(); break; + case 13: m_sSubject = pReader->GetString2(); break; + case 14: m_sVersion = pReader->GetString2(); break; + } + } + + pReader->Seek(_end_rec2); + } + break; + default: + { + pReader->SkipRecord(); + break; + } + } + } + + pReader->Seek(_end_rec); + } + void CCore::toXmlWriter(NSBinPptxRW::CXmlWriter* pWriter) const + { + pWriter->StartNode(_T("cp:coreProperties")); + + pWriter->StartAttributes(); + + pWriter->WriteAttribute(_T("xmlns:cp"), PPTX::g_Namespaces.cp.m_strLink); + pWriter->WriteAttribute(_T("xmlns:dc"), PPTX::g_Namespaces.dc.m_strLink); + pWriter->WriteAttribute(_T("xmlns:dcterms"), PPTX::g_Namespaces.dcterms.m_strLink); + pWriter->WriteAttribute(_T("xmlns:dcmitype"), PPTX::g_Namespaces.dcmitype.m_strLink); + pWriter->WriteAttribute(_T("xmlns:xsi"), PPTX::g_Namespaces.xsi.m_strLink); + + pWriter->EndAttributes(); + + pWriter->WriteNodeValue2(_T("dc:title"), m_sTitle); + pWriter->WriteNodeValue2(_T("dc:subject"), m_sSubject); + pWriter->WriteNodeValue2(_T("dc:creator"), m_sCreator); + pWriter->WriteNodeValue2(_T("cp:keywords"), m_sKeywords); + pWriter->WriteNodeValue2(_T("dc:description"), m_sDescription); + pWriter->WriteNodeValue2(_T("dc:identifier"), m_sIdentifier); + pWriter->WriteNodeValue2(_T("dc:language"), m_sLanguage); + pWriter->WriteNodeValue2(_T("cp:lastModifiedBy"), m_sLastModifiedBy); + pWriter->WriteNodeValue2(_T("cp:revision"), m_sRevision); + + if ((m_sLastPrinted.IsInit()) && (false == m_sLastPrinted->empty())) + { + pWriter->WriteNodeValue2(_T("cp:lastPrinted"), m_sLastPrinted); + } + if ((m_sCreated.IsInit()) && (false == m_sCreated->empty())) + { + pWriter->WriteNodeBegin(_T("dcterms:created xsi:type=\"dcterms:W3CDTF\"")); + pWriter->WriteStringXML(*m_sCreated); + pWriter->WriteNodeEnd(_T("dcterms:created")); + } + if ((m_sModified.IsInit()) && (false == m_sModified->empty())) + { + pWriter->WriteNodeBegin(_T("dcterms:modified xsi:type=\"dcterms:W3CDTF\"")); + pWriter->WriteStringXML(*m_sModified); + pWriter->WriteNodeEnd(_T("dcterms:modified")); + } + pWriter->WriteNodeValue2(_T("cp:category"), m_sCategory); + pWriter->WriteNodeValue2(_T("cp:contentStatus"), m_sContentStatus); + pWriter->WriteNodeValue2(_T("cp:version"), m_sVersion); + + pWriter->EndNode(_T("cp:coreProperties")); } } // namespace OOX diff --git a/OOXML/DocxFormat/Core.h b/OOXML/DocxFormat/Core.h index bb1872c86a..44e971c118 100644 --- a/OOXML/DocxFormat/Core.h +++ b/OOXML/DocxFormat/Core.h @@ -60,8 +60,9 @@ namespace OOX void SetCreator(std::wstring sVal); void SetLastModifiedBy(std::wstring sVal); - PPTX::Core* ToPptxCore(); - void FromPptxCore(PPTX::Core* pCore); + virtual void toPPTY(NSBinPptxRW::CBinaryFileWriter* pWriter) const; + virtual void fromPPTY(NSBinPptxRW::CBinaryFileReader* pReader); + virtual void toXmlWriter(NSBinPptxRW::CXmlWriter* pWriter) const; nullable_string m_sCategory; nullable_string m_sContentStatus; diff --git a/OOXML/PPTXFormat/Core.cpp b/OOXML/PPTXFormat/Core.cpp deleted file mode 100644 index 010f767eb3..0000000000 --- a/OOXML/PPTXFormat/Core.cpp +++ /dev/null @@ -1,236 +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 "Core.h" - -namespace PPTX -{ - Core::Core(OOX::Document* pMain) : WrapperFile(pMain) - { - } - Core::Core(OOX::Document* pMain, const OOX::CPath& filename, FileMap& map) : WrapperFile(pMain) - { - read(filename, map); - } - Core::~Core() - { - } - void Core::read(const OOX::CPath& filename, FileMap& map) - { - XmlUtils::CXmlNode oNode; - oNode.FromXmlFile(filename.m_strFilename); - - XmlMacroReadNodeValueBase(oNode, _T("cp:category"), category); - XmlMacroReadNodeValueBase(oNode, _T("cp:contentStatus"), contentStatus); - XmlMacroReadNodeValueBase(oNode, _T("dcterms:created"), created); - //created = PPTX::DateTime::Parse(document.Root.element("created").text().ToString()); - XmlMacroReadNodeValueBase(oNode, _T("dc:creator"), creator); - XmlMacroReadNodeValueBase(oNode, _T("dc:description"), description); - XmlMacroReadNodeValueBase(oNode, _T("dc:identifier"), identifier); - //todo keywords is complex by spec there is no real example - XmlMacroReadNodeValueBase(oNode, _T("cp:keywords"), keywords); - XmlMacroReadNodeValueBase(oNode, _T("dc:language"), language); - XmlMacroReadNodeValueBase(oNode, _T("cp:lastModifiedBy"), lastModifiedBy); - XmlMacroReadNodeValueBase(oNode, _T("cp:lastPrinted"), lastPrinted); - //lastPrinted = PPTX::DateTime::Parse(document.Root.element("lastPrinted").text().ToString()); - XmlMacroReadNodeValueBase(oNode, _T("dcterms:modified"), modified); - //modified = PPTX::DateTime::Parse(document.Root.element("modified").text().ToString()); - XmlMacroReadNodeValueBase(oNode, _T("cp:revision"), revision); - XmlMacroReadNodeValueBase(oNode, _T("dc:subject"), subject); - XmlMacroReadNodeValueBase(oNode, _T("dc:title"), title); - XmlMacroReadNodeValueBase(oNode, _T("cp:version"), version); - } - void Core::write(const OOX::CPath& filename, const OOX::CPath& directory, OOX::CContentTypes& content)const - { - WrapperFile::write(filename, directory, content); - } - const OOX::FileType Core::type() const - { - return OOX::FileTypes::Core; - } - const OOX::CPath Core::DefaultDirectory() const - { - return type().DefaultDirectory(); - } - const OOX::CPath Core::DefaultFileName() const - { - return type().DefaultFileName(); - } - void Core::toPPTY(NSBinPptxRW::CBinaryFileWriter* pWriter) const - { - pWriter->StartRecord(NSBinPptxRW::NSMainTables::Core); - - pWriter->WriteBYTE(NSBinPptxRW::g_nodeAttributeStart); - - pWriter->WriteString2(0, title); - pWriter->WriteString2(1, creator); - pWriter->WriteString2(2, lastModifiedBy); - pWriter->WriteString2(3, revision); - pWriter->WriteString2(4, created); - pWriter->WriteString2(5, modified); - - pWriter->WriteBYTE(NSBinPptxRW::g_nodeAttributeEnd); - - //start new record because new attributes is incompatible with previous versions - pWriter->StartRecord(0); - pWriter->WriteBYTE(NSBinPptxRW::g_nodeAttributeStart); - - pWriter->WriteString2(6, category); - pWriter->WriteString2(7, contentStatus); - pWriter->WriteString2(8, description); - pWriter->WriteString2(9, identifier); - pWriter->WriteString2(10, keywords); - pWriter->WriteString2(11, language); - pWriter->WriteString2(12, lastPrinted); - pWriter->WriteString2(13, subject); - pWriter->WriteString2(14, version); - - pWriter->WriteBYTE(NSBinPptxRW::g_nodeAttributeEnd); - pWriter->EndRecord(); - - pWriter->EndRecord(); - } - void Core::fromPPTY(NSBinPptxRW::CBinaryFileReader* pReader) - { - pReader->Skip(1); // type - LONG _end_rec = pReader->GetPos() + pReader->GetRecordSize() + 4; - - pReader->Skip(1); // start attributes - - while (true) - { - BYTE _at = pReader->GetUChar_TypeNode(); - if (_at == NSBinPptxRW::g_nodeAttributeEnd) - break; - - switch (_at) - { - case 0: title = pReader->GetString2(); break; - case 1: creator = pReader->GetString2(); break; - case 2: lastModifiedBy = pReader->GetString2(); break; - case 3: revision = pReader->GetString2(); break; - case 4: created = pReader->GetString2(); break; - case 5: modified = pReader->GetString2(); break; - default: break; - } - } - while (pReader->GetPos() < _end_rec) - { - BYTE _at = pReader->GetUChar(); - switch (_at) - { - case 0: - { - LONG _end_rec2 = pReader->GetPos() + pReader->GetRecordSize() + 4; - - pReader->Skip(1); // start attributes - - while (true) - { - BYTE _at = pReader->GetUChar_TypeNode(); - if (_at == NSBinPptxRW::g_nodeAttributeEnd) - break; - - switch (_at) - { - case 6: category = pReader->GetString2(); break; - case 7: contentStatus = pReader->GetString2(); break; - case 8: description = pReader->GetString2(); break; - case 9: identifier = pReader->GetString2(); break; - case 10: keywords = pReader->GetString2(); break; - case 11: language = pReader->GetString2(); break; - case 12: lastPrinted = pReader->GetString2(); break; - case 13: subject = pReader->GetString2(); break; - case 14: version = pReader->GetString2(); break; - } - } - - pReader->Seek(_end_rec2); - } - break; - default: - { - pReader->SkipRecord(); - break; - } - } - } - - pReader->Seek(_end_rec); - } - void Core::toXmlWriter(NSBinPptxRW::CXmlWriter* pWriter) const - { - pWriter->StartNode(_T("cp:coreProperties")); - - pWriter->StartAttributes(); - - pWriter->WriteAttribute(_T("xmlns:cp"), PPTX::g_Namespaces.cp.m_strLink); - pWriter->WriteAttribute(_T("xmlns:dc"), PPTX::g_Namespaces.dc.m_strLink); - pWriter->WriteAttribute(_T("xmlns:dcterms"), PPTX::g_Namespaces.dcterms.m_strLink); - pWriter->WriteAttribute(_T("xmlns:dcmitype"), PPTX::g_Namespaces.dcmitype.m_strLink); - pWriter->WriteAttribute(_T("xmlns:xsi"), PPTX::g_Namespaces.xsi.m_strLink); - - pWriter->EndAttributes(); - - pWriter->WriteNodeValue2(_T("dc:title"), title); - pWriter->WriteNodeValue2(_T("dc:subject"), subject); - pWriter->WriteNodeValue2(_T("dc:creator"), creator); - pWriter->WriteNodeValue2(_T("cp:keywords"), keywords); - pWriter->WriteNodeValue2(_T("dc:description"), description); - pWriter->WriteNodeValue2(_T("dc:identifier"), identifier); - pWriter->WriteNodeValue2(_T("dc:language"), language); - pWriter->WriteNodeValue2(_T("cp:lastModifiedBy"), lastModifiedBy); - pWriter->WriteNodeValue2(_T("cp:revision"), revision); - - if ((lastPrinted.IsInit()) && (false == lastPrinted->empty())) - { - pWriter->WriteNodeValue2(_T("cp:lastPrinted"), lastPrinted); - } - if ((created.IsInit()) && (false == created->empty())) - { - pWriter->WriteNodeBegin(_T("dcterms:created xsi:type=\"dcterms:W3CDTF\"")); - pWriter->WriteStringXML(*created); - pWriter->WriteNodeEnd(_T("dcterms:created")); - } - if ((modified.IsInit()) && (false == modified->empty())) - { - pWriter->WriteNodeBegin(_T("dcterms:modified xsi:type=\"dcterms:W3CDTF\"")); - pWriter->WriteStringXML(*modified); - pWriter->WriteNodeEnd(_T("dcterms:modified")); - } - pWriter->WriteNodeValue2(_T("cp:category"), category); - pWriter->WriteNodeValue2(_T("cp:contentStatus"), contentStatus); - pWriter->WriteNodeValue2(_T("cp:version"), version); - - pWriter->EndNode(_T("cp:coreProperties")); - } -} // namespace PPTX diff --git a/OOXML/PPTXFormat/Core.h b/OOXML/PPTXFormat/Core.h deleted file mode 100644 index 709993b5ae..0000000000 --- a/OOXML/PPTXFormat/Core.h +++ /dev/null @@ -1,83 +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 - * - */ -#pragma once - -#include "WrapperFile.h" -#include "../DocxFormat/WritingElement.h" - -#include "Limit/ContentStatus.h" -#include "FileTypes.h" - -namespace PPTX -{ - class Core : public WrapperFile - { - public: - Core(OOX::Document* pMain); - Core(OOX::Document* pMain, const OOX::CPath& filename, FileMap& map); - virtual ~Core(); - - public: - virtual void read(const OOX::CPath& filename, FileMap& map); - virtual void write(const OOX::CPath& filename, const OOX::CPath& directory, OOX::CContentTypes& content) const; - - public: - virtual const OOX::FileType type() const; - - virtual const OOX::CPath DefaultDirectory() const; - virtual const OOX::CPath DefaultFileName() const; - - virtual void toPPTY(NSBinPptxRW::CBinaryFileWriter* pWriter) const; - virtual void fromPPTY(NSBinPptxRW::CBinaryFileReader* pReader); - virtual void toXmlWriter(NSBinPptxRW::CXmlWriter* pWriter) const; - - public: - nullable_string category; - nullable_string contentStatus; - //nullable_property contentStatus; - nullable_string created; - //nullable_property created; - nullable_string creator; - nullable_string description; - nullable_string identifier; - nullable_string keywords; - nullable_string language; - nullable_string lastModifiedBy; - nullable_string lastPrinted; - nullable_string modified; - //nullable_property modified; - nullable_string revision; - nullable_string subject; - nullable_string title; - nullable_string version; - }; -} // namespace PPTX diff --git a/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.cpp b/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.cpp index 1df5b6c73d..21313f4b80 100644 --- a/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.cpp +++ b/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.cpp @@ -2845,7 +2845,7 @@ void CDrawingConverter::ConvertShape(PPTX::Logic::SpTreeElem *elem, XmlUtils::CX { pCNvPr->hidden = true; } - + CSpTreeElemProps oProps; oProps.IsTop = bIsTop; std::wstring strMainPos = GetDrawingMainProps(oNodeShape, oCSSParser, oProps); @@ -2986,6 +2986,13 @@ void CDrawingConverter::ConvertShape(PPTX::Logic::SpTreeElem *elem, XmlUtils::CX CheckBrushShape(elem, oNodeShape, pPPTShape); CheckBorderShape(elem, oNodeShape, pPPTShape); + +////test +// NSBinPptxRW::CXmlWriter oXml; +// elem->toXmlWriter(&oXml); +// std::wstring test = oXml.GetXmlString(); + + } } void CDrawingConverter::ConvertWordArtShape(PPTX::Logic::SpTreeElem* elem, XmlUtils::CXmlNode& oNodeShape, CPPTShape* pPPTShape) @@ -4548,8 +4555,14 @@ std::wstring CDrawingConverter::GetDrawingMainProps(XmlUtils::CXmlNode& oNode, P oWriter.EndNode(L"wp14:pctHeight"); oWriter.EndNode(L"wp14:sizeRelV"); } + nullable_string alt_content; + XmlMacroReadAttributeBase(oNode, L"alt", alt_content); - std::wstring strId = L"