mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-03-14 00:56:04 +08:00
Compare commits
32 Commits
feature/so
...
v9.4.0.18
| Author | SHA1 | Date | |
|---|---|---|---|
| da769a642b | |||
| 12083ae8c9 | |||
| 6819a41452 | |||
| 5d5732161a | |||
| 21dd6c2a61 | |||
| b607aeb4c6 | |||
| e1b3fe270a | |||
| 615cf0982d | |||
| a027644bf0 | |||
| 9983161e3d | |||
| 33c4b5130e | |||
| 0101774675 | |||
| de9709ea50 | |||
| 22e7c5bed4 | |||
| eada4b4ebe | |||
| 57ca5da2c0 | |||
| 08bad0753a | |||
| 6224b6384d | |||
| be1aed4cae | |||
| 3676400e66 | |||
| 3b0c9cea7e | |||
| 3dc0f482c8 | |||
| d17c22772f | |||
| 2a09f9da90 | |||
| df576b6e99 | |||
| b430c3f296 | |||
| c21827825b | |||
| 0424c73db0 | |||
| dc6a72892c | |||
| 927f49291a | |||
| cf72c836a1 | |||
| b9a905f6b2 |
@ -0,0 +1,5 @@
|
||||
<<<<<<<
|
||||
if((c >= 'a' && c <= 'z') || (c>= 'A' && c<= 'Z') || (c >= '0' && c<= '9')){
|
||||
=======
|
||||
if((c >= 'a' && c <= 'z') || (c>= 'A' && c<= 'Z') || (c >= '0' && c<= '9') || ('-' == c) || ('_' == c) || ('.' == c) || ('~' == c)){
|
||||
>>>>>>>
|
||||
@ -105,11 +105,37 @@ namespace NSNetwork
|
||||
{
|
||||
static NSString* StringWToNSString ( const std::wstring& Str )
|
||||
{
|
||||
// Returns +1 retained NSString (alloc/init). Caller must release in non-ARC.
|
||||
NSString* pString = [ [ NSString alloc ]
|
||||
initWithBytes : (char*)Str.data() length : Str.size() * sizeof(wchar_t)
|
||||
encoding : CFStringConvertEncodingToNSStringEncoding ( kCFStringEncodingUTF32LE ) ];
|
||||
initWithBytes : (char*)Str.data() length : Str.size() * sizeof(wchar_t)
|
||||
encoding : CFStringConvertEncodingToNSStringEncoding ( kCFStringEncodingUTF32LE ) ];
|
||||
return pString;
|
||||
}
|
||||
|
||||
// NSURLComponents correctly handles mixed input (already-encoded + raw characters)
|
||||
// without double-encoding, but normalises unreserved percent-sequences (%5F → _).
|
||||
// If preserving the exact encoding is required, use [NSURL URLWithString:] instead.
|
||||
static NSURL* SafeURLFromString(NSString* urlString)
|
||||
{
|
||||
if (!urlString || urlString.length == 0)
|
||||
return nil;
|
||||
|
||||
NSURL* url = [NSURL URLWithString:urlString];
|
||||
if (url)
|
||||
return url;
|
||||
|
||||
// Fallback: the string contains unencoded characters (spaces, cyrillic,
|
||||
// brackets, etc.). URLFragmentAllowedCharacterSet includes '%', so
|
||||
// existing percent-sequences won't be double-encoded.
|
||||
NSString* encoded =
|
||||
[urlString stringByAddingPercentEncodingWithAllowedCharacters:
|
||||
[NSCharacterSet URLFragmentAllowedCharacterSet]];
|
||||
if (!encoded)
|
||||
return nil;
|
||||
|
||||
return [NSURL URLWithString:encoded];
|
||||
}
|
||||
|
||||
class CFileTransporterBaseCocoa : public CFileTransporterBase
|
||||
{
|
||||
public :
|
||||
@ -145,83 +171,162 @@ namespace NSNetwork
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
// stringURL: +1 retained (alloc/init). Must be released on all exit paths in non-ARC.
|
||||
NSString* stringURL = StringWToNSString(m_sDownloadFileUrl);
|
||||
NSString* escapedURL = [stringURL stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
|
||||
NSURL* url = SafeURLFromString(stringURL);
|
||||
|
||||
int nResult = 1;
|
||||
|
||||
if (m_pSession)
|
||||
if (!url)
|
||||
{
|
||||
NSURLRequest* urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:escapedURL]];
|
||||
|
||||
__block NSData* result = nil;
|
||||
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
|
||||
|
||||
NSURLSession* _session = ((CSessionMAC*)m_pSession->m_pInternal)->m_session;
|
||||
if (nil == _session)
|
||||
_session = [NSURLSession sharedSession];
|
||||
|
||||
[[_session dataTaskWithRequest:urlRequest
|
||||
completionHandler:^(NSData *data, NSURLResponse* response, NSError *error) {
|
||||
if (error == nil)
|
||||
result = data;
|
||||
|
||||
dispatch_semaphore_signal(sem);
|
||||
}] resume];
|
||||
|
||||
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
|
||||
|
||||
if (result)
|
||||
{
|
||||
NSString* filePath = StringWToNSString(m_sDownloadFilePath);
|
||||
[result writeToFile:filePath atomically:YES];
|
||||
|
||||
nResult = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
nResult = 1;
|
||||
}
|
||||
|
||||
return nResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSURL* url = [NSURL URLWithString:escapedURL];
|
||||
NSData* urlData = [[NSData alloc] initWithContentsOfURL:url];
|
||||
if ( urlData )
|
||||
{
|
||||
NSString* filePath = StringWToNSString(m_sDownloadFilePath);
|
||||
[urlData writeToFile:filePath atomically:YES];
|
||||
|
||||
#if defined(_IOS)
|
||||
return 0;
|
||||
#else
|
||||
#ifndef _ASC_USE_ARC_
|
||||
if (!GetARCEnabled())
|
||||
{
|
||||
[stringURL release];
|
||||
//[url release];
|
||||
[urlData release];
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(_IOS)
|
||||
NSLog(@"[DownloadFile] Invalid URL: %@", stringURL);
|
||||
#if !defined(_IOS)
|
||||
#ifndef _ASC_USE_ARC_
|
||||
if (!GetARCEnabled())
|
||||
[stringURL release];
|
||||
#endif
|
||||
#endif
|
||||
return 1;
|
||||
#else
|
||||
#ifndef _ASC_USE_ARC_
|
||||
}
|
||||
|
||||
// Select session. If the caller provided one, prefer it; fall back to the shared
|
||||
// singleton. [NSURLSession sharedSession] is a singleton -- never retain/release it.
|
||||
NSURLSession* session = nil;
|
||||
if (m_pSession && m_pSession->m_pInternal)
|
||||
{
|
||||
CSessionMAC* sessionInternal = (CSessionMAC*)m_pSession->m_pInternal;
|
||||
session = sessionInternal->m_session;
|
||||
}
|
||||
if (!session)
|
||||
session = [NSURLSession sharedSession];
|
||||
|
||||
// NSData initWithContentsOfURL / dataWithContentsOfURL must NOT be used for HTTP:
|
||||
// - Fails silently on CDN responses with Transfer-Encoding: chunked
|
||||
// (returns NSCocoaErrorDomain Code=256 on some iOS versions)
|
||||
// - Does not follow HTTP redirects reliably
|
||||
// - Ignores Content-Encoding (gzip, br)
|
||||
// - Has no timeout, can block indefinitely
|
||||
// NSURLSession handles all of the above correctly on all supported iOS/macOS versions.
|
||||
NSURLRequest* urlRequest = [NSURLRequest requestWithURL:url];
|
||||
|
||||
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
|
||||
|
||||
// In non-ARC, __block variables are NOT automatically retained by the block.
|
||||
// |data| passed to the completion handler is autoreleased; without an explicit
|
||||
// retain it may be deallocated before semaphore_wait returns on the calling thread.
|
||||
// We therefore retain inside the block and release after use below.
|
||||
__block NSData* resultData = nil;
|
||||
|
||||
NSURLSessionDataTask* task =
|
||||
[session dataTaskWithRequest:urlRequest
|
||||
completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
NSLog(@"[DownloadFile] Network error: %@, URL: %@", error, url);
|
||||
}
|
||||
else if ([response isKindOfClass:[NSHTTPURLResponse class]])
|
||||
{
|
||||
NSInteger status = [(NSHTTPURLResponse*)response statusCode];
|
||||
if (status >= 200 && status < 300)
|
||||
{
|
||||
#if !defined(_IOS)
|
||||
#ifndef _ASC_USE_ARC_
|
||||
if (!GetARCEnabled())
|
||||
resultData = [data retain];
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
resultData = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"[DownloadFile] HTTP %ld, URL: %@", (long)status, url);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Non-HTTP scheme (e.g. file://) -- accept unconditionally.
|
||||
#if !defined(_IOS)
|
||||
#ifndef _ASC_USE_ARC_
|
||||
if (!GetARCEnabled())
|
||||
resultData = [data retain];
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
resultData = data;
|
||||
}
|
||||
|
||||
dispatch_semaphore_signal(sem);
|
||||
}];
|
||||
|
||||
[task resume];
|
||||
|
||||
// 60-second hard timeout. DISPATCH_TIME_FOREVER must not be used: if the network
|
||||
// stack silently drops the connection the completion handler may never fire,
|
||||
// leaving this thread suspended indefinitely (deadlock).
|
||||
const int64_t kTimeoutSeconds = 60;
|
||||
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, kTimeoutSeconds * NSEC_PER_SEC);
|
||||
long waitResult = dispatch_semaphore_wait(sem, timeout);
|
||||
|
||||
// dispatch_semaphore_create returns a +1 object. Release it in non-ARC.
|
||||
// In ARC (including all iOS targets) GCD objects are managed automatically.
|
||||
#if !defined(_IOS)
|
||||
#ifndef _ASC_USE_ARC_
|
||||
if (!GetARCEnabled())
|
||||
dispatch_release(sem);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (waitResult != 0)
|
||||
{
|
||||
// Timeout expired. Cancel the in-flight task so that the completion handler
|
||||
// is called with NSURLErrorCancelled (data == nil), preventing it from writing
|
||||
// to resultData after we return and corrupting memory in non-ARC.
|
||||
[task cancel];
|
||||
NSLog(@"[DownloadFile] Timeout after %llds, URL: %@", (long long)kTimeoutSeconds, url);
|
||||
#if !defined(_IOS)
|
||||
#ifndef _ASC_USE_ARC_
|
||||
if (!GetARCEnabled())
|
||||
{
|
||||
// resultData could theoretically be non-nil if the completion handler
|
||||
// raced with the timeout check on a multicore device before cancel ran.
|
||||
[resultData release];
|
||||
[stringURL release];
|
||||
//[url release];
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!resultData)
|
||||
{
|
||||
#if !defined(_IOS)
|
||||
#ifndef _ASC_USE_ARC_
|
||||
if (!GetARCEnabled())
|
||||
[stringURL release];
|
||||
#endif
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
// filePath: +1 retained (alloc/init). Must be released in non-ARC.
|
||||
NSString* filePath = StringWToNSString(m_sDownloadFilePath);
|
||||
BOOL written = [resultData writeToFile:filePath atomically:YES];
|
||||
|
||||
if (!written)
|
||||
NSLog(@"[DownloadFile] Failed to write file: %@", filePath);
|
||||
|
||||
#if !defined(_IOS)
|
||||
#ifndef _ASC_USE_ARC_
|
||||
if (!GetARCEnabled())
|
||||
{
|
||||
[resultData release];
|
||||
[filePath release];
|
||||
[stringURL release];
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return written ? 0 : 1;
|
||||
}
|
||||
|
||||
virtual int UploadData() override
|
||||
|
||||
@ -1374,6 +1374,25 @@ namespace Aggplus
|
||||
}
|
||||
}
|
||||
|
||||
template<class span_gen_type>
|
||||
void CGraphics::render_blendmode(span_gen_type& sg, span_alloc_type& span_allocator, BYTE Alpha)
|
||||
{
|
||||
if (m_nBlendMode != agg::comp_op_src_over)
|
||||
{
|
||||
typedef agg::renderer_scanline_aa<comp_renderer_type, span_alloc_type, span_gen_type> aa_renderer_type;
|
||||
pixfmt_type_comp pixfmt(m_frame_buffer.ren_buf(), m_nBlendMode);
|
||||
comp_renderer_type ren_base(pixfmt);
|
||||
aa_renderer_type ri(ren_base, span_allocator, sg);
|
||||
render_scanlines_alpha(ri, Alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
|
||||
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
|
||||
render_scanlines_alpha(ri, Alpha);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Renderer>
|
||||
void CGraphics::render_scanlines(Renderer& ren)
|
||||
{
|
||||
@ -1417,12 +1436,9 @@ namespace Aggplus
|
||||
if (m_nBlendMode != agg::comp_op_src_over)
|
||||
{
|
||||
typedef agg::renderer_scanline_aa_solid<comp_renderer_type> solid_comp_renderer_type;
|
||||
solid_comp_renderer_type ren_solid;
|
||||
comp_renderer_type ren_base;
|
||||
pixfmt_type_comp pixfmt(m_frame_buffer.ren_buf(), m_nBlendMode);
|
||||
|
||||
ren_base.attach(pixfmt);
|
||||
ren_solid.attach(ren_base);
|
||||
comp_renderer_type ren_base(pixfmt);
|
||||
solid_comp_renderer_type ren_solid(ren_base);
|
||||
|
||||
ren_solid.color(dwColor.GetAggColor());
|
||||
render_scanlines(ren_solid);
|
||||
@ -1727,6 +1743,70 @@ namespace Aggplus
|
||||
}
|
||||
}
|
||||
|
||||
template<typename pixfmt>
|
||||
void CGraphics::DoFillPathTextureClampSz2_Impl(agg::rendering_buffer& PatRendBuff, interpolator_type_linear& interpolator, span_alloc_type& span_allocator, int nCurrentMode, BYTE Alpha)
|
||||
{
|
||||
typedef agg::image_accessor_clone<pixfmt> img_source_type;
|
||||
pixfmt img_pixf(PatRendBuff);
|
||||
img_source_type img_src(img_pixf);
|
||||
|
||||
switch (nCurrentMode)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
typedef agg::span_image_filter_rgba_nn<img_source_type, interpolator_type_linear> span_gen_type;
|
||||
span_gen_type sg(img_src, interpolator);
|
||||
render_blendmode(sg, span_allocator, Alpha);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
typedef agg::span_image_filter_rgba_bilinear<img_source_type, interpolator_type_linear> span_gen_type;
|
||||
span_gen_type sg(img_src, interpolator);
|
||||
render_blendmode(sg, span_allocator, Alpha);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
typedef agg::span_image_filter_rgba_2x2<img_source_type, interpolator_type_linear> span_gen_type;
|
||||
agg::image_filter_lut filter;
|
||||
filter.calculate(agg::image_filter_bicubic(), false);
|
||||
span_gen_type sg(img_src, interpolator, filter);
|
||||
render_blendmode(sg, span_allocator, Alpha);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
typedef agg::span_image_filter_rgba_2x2<img_source_type, interpolator_type_linear> span_gen_type;
|
||||
agg::image_filter_lut filter;
|
||||
filter.calculate(agg::image_filter_spline16(), false);
|
||||
span_gen_type sg(img_src, interpolator, filter);
|
||||
render_blendmode(sg, span_allocator, Alpha);
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
typedef agg::span_image_filter_rgba_2x2<img_source_type, interpolator_type_linear> span_gen_type;
|
||||
agg::image_filter_lut filter;
|
||||
filter.calculate(agg::image_filter_blackman256(), false);
|
||||
span_gen_type sg(img_src, interpolator, filter);
|
||||
render_blendmode(sg, span_allocator, Alpha);
|
||||
break;
|
||||
}
|
||||
case 255:
|
||||
{
|
||||
typedef agg::span_image_resample_rgba_affine_for_draw<img_source_type> span_gen_type;
|
||||
agg::image_filter_lut filter;
|
||||
filter.calculate(agg::image_filter_bilinear(), false);
|
||||
span_gen_type sg(img_src, interpolator, filter);
|
||||
render_blendmode(sg, span_allocator, Alpha);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CGraphics::DoFillPathTextureClampSz2(const CMatrix &mImgMtx, const void *pImgBuff, DWORD dwImgWidth, DWORD dwImgHeight, int nImgStride, BYTE Alpha)
|
||||
{
|
||||
span_alloc_type span_allocator;
|
||||
@ -1738,158 +1818,11 @@ namespace Aggplus
|
||||
PatRendBuff.attach((BYTE*)pImgBuff, dwImgWidth, dwImgHeight, nImgStride);
|
||||
|
||||
int nCurrentMode = 255;
|
||||
|
||||
if (!m_bSwapRGB)
|
||||
{
|
||||
typedef agg::pixfmt_bgra32 pixfmt;
|
||||
typedef agg::image_accessor_clone<pixfmt> img_source_type;
|
||||
|
||||
pixfmt img_pixf(PatRendBuff);
|
||||
img_source_type img_src(img_pixf);
|
||||
|
||||
switch (nCurrentMode)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
typedef agg::span_image_filter_rgba_nn<img_source_type, interpolator_type_linear> span_gen_type;
|
||||
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
|
||||
span_gen_type sg(img_src, interpolator);
|
||||
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
|
||||
render_scanlines_alpha(ri, Alpha);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
typedef agg::span_image_filter_rgba_bilinear<img_source_type, interpolator_type_linear> span_gen_type;
|
||||
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
|
||||
span_gen_type sg(img_src, interpolator);
|
||||
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
|
||||
render_scanlines_alpha(ri, Alpha);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
typedef agg::span_image_filter_rgba_2x2<img_source_type, interpolator_type_linear> span_gen_type;
|
||||
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
|
||||
agg::image_filter_lut filter;
|
||||
filter.calculate(agg::image_filter_bicubic(), false);
|
||||
span_gen_type sg(img_src, interpolator, filter);
|
||||
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
|
||||
render_scanlines_alpha(ri, Alpha);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
typedef agg::span_image_filter_rgba_2x2<img_source_type, interpolator_type_linear> span_gen_type;
|
||||
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
|
||||
agg::image_filter_lut filter;
|
||||
filter.calculate(agg::image_filter_spline16(), false);
|
||||
span_gen_type sg(img_src, interpolator, filter);
|
||||
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
|
||||
render_scanlines_alpha(ri, Alpha);
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
typedef agg::span_image_filter_rgba_2x2<img_source_type, interpolator_type_linear> span_gen_type;
|
||||
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
|
||||
agg::image_filter_lut filter;
|
||||
filter.calculate(agg::image_filter_blackman256(), false);
|
||||
span_gen_type sg(img_src, interpolator, filter);
|
||||
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
|
||||
render_scanlines_alpha(ri, Alpha);
|
||||
break;
|
||||
}
|
||||
case 255:
|
||||
{
|
||||
typedef agg::span_image_resample_rgba_affine_for_draw<img_source_type> span_gen_type;
|
||||
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
|
||||
agg::image_filter_lut filter;
|
||||
filter.calculate(agg::image_filter_bilinear(), false);
|
||||
span_gen_type sg(img_src, interpolator, filter);
|
||||
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
|
||||
render_scanlines_alpha(ri, Alpha);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoFillPathTextureClampSz2_Impl<agg::pixfmt_bgra32>(PatRendBuff, interpolator, span_allocator, nCurrentMode, Alpha);
|
||||
else
|
||||
{
|
||||
typedef agg::pixfmt_rgba32 pixfmt;
|
||||
typedef agg::image_accessor_clone<pixfmt> img_source_type;
|
||||
|
||||
pixfmt img_pixf(PatRendBuff);
|
||||
img_source_type img_src(img_pixf);
|
||||
|
||||
switch (nCurrentMode)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
typedef agg::span_image_filter_rgba_nn<img_source_type, interpolator_type_linear> span_gen_type;
|
||||
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
|
||||
span_gen_type sg(img_src, interpolator);
|
||||
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
|
||||
render_scanlines_alpha(ri, Alpha);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
typedef agg::span_image_filter_rgba_bilinear<img_source_type, interpolator_type_linear> span_gen_type;
|
||||
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
|
||||
span_gen_type sg(img_src, interpolator);
|
||||
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
|
||||
render_scanlines_alpha(ri, Alpha);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
typedef agg::span_image_filter_rgba_2x2<img_source_type, interpolator_type_linear> span_gen_type;
|
||||
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
|
||||
agg::image_filter_lut filter;
|
||||
filter.calculate(agg::image_filter_bicubic(), false);
|
||||
span_gen_type sg(img_src, interpolator, filter);
|
||||
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
|
||||
render_scanlines_alpha(ri, Alpha);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
typedef agg::span_image_filter_rgba_2x2<img_source_type, interpolator_type_linear> span_gen_type;
|
||||
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
|
||||
agg::image_filter_lut filter;
|
||||
filter.calculate(agg::image_filter_spline16(), false);
|
||||
span_gen_type sg(img_src, interpolator, filter);
|
||||
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
|
||||
render_scanlines_alpha(ri, Alpha);
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
typedef agg::span_image_filter_rgba_2x2<img_source_type, interpolator_type_linear> span_gen_type;
|
||||
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
|
||||
agg::image_filter_lut filter;
|
||||
filter.calculate(agg::image_filter_blackman256(), false);
|
||||
span_gen_type sg(img_src, interpolator, filter);
|
||||
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
|
||||
render_scanlines_alpha(ri, Alpha);
|
||||
break;
|
||||
}
|
||||
case 255:
|
||||
{
|
||||
typedef agg::span_image_resample_rgba_affine_for_draw<img_source_type> span_gen_type;
|
||||
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
|
||||
agg::image_filter_lut filter;
|
||||
filter.calculate(agg::image_filter_bilinear(), false);
|
||||
span_gen_type sg(img_src, interpolator, filter);
|
||||
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
|
||||
render_scanlines_alpha(ri, Alpha);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoFillPathTextureClampSz2_Impl<agg::pixfmt_rgba32>(PatRendBuff, interpolator, span_allocator, nCurrentMode, Alpha);
|
||||
}
|
||||
|
||||
template<class ColorSpacePix>
|
||||
|
||||
@ -430,6 +430,9 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
template<class span_gen_type>
|
||||
void render_blendmode(span_gen_type& sg, span_alloc_type& span_allocator, BYTE Alpha);
|
||||
|
||||
template<class Renderer>
|
||||
void render_scanlines(Renderer& ren);
|
||||
template<class Rasterizer, class Renderer>
|
||||
@ -447,6 +450,9 @@ protected:
|
||||
//--test
|
||||
void DoFillPathHatch(CBrushHatch *pBrush);
|
||||
void DoFillPathTextureClampSz(const CMatrix &mImgMtx, const void *pImgBuff, DWORD dwImgWidth, DWORD dwImgHeight, int nImgStride);
|
||||
|
||||
template<typename pixfmt>
|
||||
void DoFillPathTextureClampSz2_Impl(agg::rendering_buffer& PatRendBuff, interpolator_type_linear& interpolator, span_alloc_type& span_allocator, int nCurrentMode, BYTE Alpha);
|
||||
void DoFillPathTextureClampSz2(const CMatrix &mImgMtx, const void *pImgBuff, DWORD dwImgWidth, DWORD dwImgHeight, int nImgStride, BYTE Alpha = 255);
|
||||
|
||||
template<class ColorSpacePix>
|
||||
|
||||
@ -726,7 +726,7 @@ unsigned char* CDjVuFileImplementation::ConvertToPixels(int nPageIndex, int nRas
|
||||
GP<DjVuImage> pPage = m_pDoc->get_page(nPageIndex);
|
||||
//pPage->wait_for_complete_decode();
|
||||
pPage->set_rotate(0);
|
||||
return ConvertToPixels(pPage, nRasterW, nRasterH, bIsFlip);
|
||||
return ConvertToPixels(pPage, nRasterW, nRasterH, bIsFlip, true);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@ -734,11 +734,11 @@ unsigned char* CDjVuFileImplementation::ConvertToPixels(int nPageIndex, int nRas
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned char* CDjVuFileImplementation::ConvertToPixels(GP<DjVuImage>& pPage, int nImageW, int nImageH, bool bFlip)
|
||||
unsigned char* CDjVuFileImplementation::ConvertToPixels(GP<DjVuImage>& pPage, int nImageW, int nImageH, bool bFlip, bool bIsSwapRGB)
|
||||
{
|
||||
BYTE* pBufferDst = NULL;
|
||||
|
||||
auto processPixmap = [&](GP<GPixmap> pImage, bool bFlip = false)
|
||||
auto processPixmap = [&](GP<GPixmap> pImage, bool bFlip = false, bool bIsSwapRGB = false)
|
||||
{
|
||||
pBufferDst = new BYTE[4 * nImageW * nImageH];
|
||||
|
||||
@ -749,7 +749,10 @@ unsigned char* CDjVuFileImplementation::ConvertToPixels(GP<DjVuImage>& pPage, in
|
||||
GPixel* pLine = pImage->operator[](nRow);
|
||||
for (int i = 0; i < nImageW; ++i)
|
||||
{
|
||||
*pBuffer++ = 0xFF000000 | pLine->r << 16 | pLine->g << 8 | pLine->b;
|
||||
if (bIsSwapRGB)
|
||||
*pBuffer++ = 0xFF000000 | pLine->b << 16 | pLine->g << 8 | pLine->r;
|
||||
else
|
||||
*pBuffer++ = 0xFF000000 | pLine->r << 16 | pLine->g << 8 | pLine->b;
|
||||
++pLine;
|
||||
}
|
||||
}
|
||||
@ -790,7 +793,7 @@ unsigned char* CDjVuFileImplementation::ConvertToPixels(GP<DjVuImage>& pPage, in
|
||||
if (pPage->is_legal_photo() || pPage->is_legal_compound())
|
||||
{
|
||||
GP<GPixmap> pImage = pPage->get_pixmap(oRectAll, oRectAll);
|
||||
processPixmap(pImage, bFlip);
|
||||
processPixmap(pImage, bFlip, bIsSwapRGB);
|
||||
}
|
||||
else if (pPage->is_legal_bilevel())
|
||||
{
|
||||
@ -802,7 +805,7 @@ unsigned char* CDjVuFileImplementation::ConvertToPixels(GP<DjVuImage>& pPage, in
|
||||
GP<GPixmap> pImage = pPage->get_pixmap(oRectAll, oRectAll);
|
||||
if (pImage)
|
||||
{
|
||||
processPixmap(pImage, bFlip);
|
||||
processPixmap(pImage, bFlip, bIsSwapRGB);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -83,7 +83,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
unsigned char* ConvertToPixels(GP<DjVuImage>& pPage, int nRasterW, int nRasterH, bool bIsFlip = false);
|
||||
unsigned char* ConvertToPixels(GP<DjVuImage>& pPage, int nRasterW, int nRasterH, bool bIsFlip = false, bool bIsSwapRGB = false);
|
||||
|
||||
void CreateFrame(IRenderer* pRenderer, GP<DjVuImage>& pImage, int nPage, XmlUtils::CXmlNode& oText);
|
||||
void CreatePdfFrame(IRenderer* pRenderer, GP<DjVuImage>& pImage, int nPage, XmlUtils::CXmlNode& oText);
|
||||
|
||||
@ -765,7 +765,7 @@ namespace NSCommon
|
||||
protected:
|
||||
bool set(const std::wstring& value)
|
||||
{
|
||||
if ((L"true" == value) || (L"1" == value))
|
||||
if ((L"true" == value) || (L"1" == value) || (L"t" == value))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -148,6 +148,7 @@ namespace NSBinPptxRW
|
||||
#define GEOMETRY_TYPE_NONE 0
|
||||
#define GEOMETRY_TYPE_PRST 1
|
||||
#define GEOMETRY_TYPE_CUSTOM 2
|
||||
#define GEOMETRY_TYPE_HORIZONTALRULE 3
|
||||
|
||||
#define GEOMETRY_TYPE_AH_NONE 0
|
||||
#define GEOMETRY_TYPE_AH_POLAR 1
|
||||
|
||||
@ -227,7 +227,7 @@ namespace OOX
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
CDocument::CDocument(OOX::Document *pMain, OOX::FileType type)
|
||||
: File(pMain), IFileContainer(pMain), WritingElement(pMain)
|
||||
: File(pMain), IFileContainer(pMain), WritingElementWithChilds<>(pMain)
|
||||
{
|
||||
m_bMacroEnabled = false;
|
||||
|
||||
@ -254,7 +254,7 @@ namespace OOX
|
||||
}
|
||||
}
|
||||
CDocument::CDocument(OOX::Document *pMain, const CPath& oRootPath, const CPath& oPath, OOX::FileType type)
|
||||
: File(pMain), IFileContainer(pMain), WritingElement(pMain)
|
||||
: File(pMain), IFileContainer(pMain), WritingElementWithChilds<>(pMain)
|
||||
{
|
||||
m_bMacroEnabled = false;
|
||||
|
||||
@ -302,13 +302,13 @@ namespace OOX
|
||||
docx->m_bGlossaryRead = false;
|
||||
}
|
||||
}
|
||||
CDocument::CDocument(XmlUtils::CXmlNode& oNode) : File(NULL), IFileContainer(NULL), WritingElement(NULL)
|
||||
CDocument::CDocument(XmlUtils::CXmlNode& oNode) : File(NULL), IFileContainer(NULL), WritingElementWithChilds<>(NULL)
|
||||
{
|
||||
m_bMacroEnabled = false;
|
||||
|
||||
fromXML( oNode );
|
||||
}
|
||||
CDocument::CDocument(XmlUtils::CXmlLiteReader& oReader) : File(NULL), IFileContainer(NULL), WritingElement(NULL)
|
||||
CDocument::CDocument(XmlUtils::CXmlLiteReader& oReader) : File(NULL), IFileContainer(NULL), WritingElementWithChilds<>(NULL)
|
||||
{
|
||||
m_bMacroEnabled = false;
|
||||
|
||||
@ -403,8 +403,7 @@ namespace OOX
|
||||
{
|
||||
if (document->m_arrSections.empty())
|
||||
{
|
||||
OOX::CDocument::_section section;
|
||||
document->m_arrSections.push_back(section);
|
||||
document->m_arrSections.emplace_back();
|
||||
}
|
||||
document->m_arrSections.back().sect = m_oSectPr.GetPointer();
|
||||
document->m_arrSections.back().end_elm = document->m_arrItems.size(); //активный рутовый еще не добавлен
|
||||
@ -492,11 +491,7 @@ namespace OOX
|
||||
|
||||
void CDocument::ClearItems()
|
||||
{
|
||||
for ( size_t i = 0; i < m_arrItems.size(); ++i)
|
||||
{
|
||||
if ( m_arrItems[i] )delete m_arrItems[i];
|
||||
}
|
||||
m_arrItems.clear();
|
||||
WritingElementWithChilds<>::ClearItems();
|
||||
//----------
|
||||
m_arrSections.clear();
|
||||
}
|
||||
|
||||
@ -127,7 +127,7 @@ namespace OOX
|
||||
//--------------------------------------------------------------------------------
|
||||
// CDocument 17.2.3 (Part 1)
|
||||
//--------------------------------------------------------------------------------
|
||||
class CDocument : public OOX::File, public IFileContainer, public WritingElement
|
||||
class CDocument : public OOX::File, public IFileContainer, public WritingElementWithChilds<>
|
||||
{
|
||||
public:
|
||||
CDocument(OOX::Document *pMain = NULL, OOX::FileType type = OOX::FileTypes::Document);
|
||||
@ -171,8 +171,6 @@ namespace OOX
|
||||
|
||||
nullable<OOX::Logic::CSectionProperty> m_oSectPr;
|
||||
nullable<OOX::Logic::CBackground> m_oBackground;
|
||||
|
||||
std::vector<WritingElement*> m_arrItems;
|
||||
//---------------------------------------------------------------------------------------------
|
||||
struct _section
|
||||
{
|
||||
|
||||
@ -185,10 +185,10 @@ namespace OOX
|
||||
{
|
||||
if (m_oParagraphProperty)
|
||||
{
|
||||
CParagraphProperty prop2(oItem);
|
||||
CParagraphProperty newProp = CParagraphProperty::Merge(*m_oParagraphProperty, prop2);
|
||||
|
||||
pItem = m_oParagraphProperty = new CParagraphProperty(newProp);
|
||||
pItem = new CParagraphProperty(*m_oParagraphProperty);
|
||||
pItem->fromXML(oItem);
|
||||
|
||||
m_oParagraphProperty = dynamic_cast<CParagraphProperty*>(pItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -331,12 +331,10 @@ namespace OOX
|
||||
{// c копией .. для быстрого доступа/анализа
|
||||
if (m_oParagraphProperty)
|
||||
{
|
||||
CParagraphProperty prop2(document);
|
||||
prop2.fromXML(oReader);
|
||||
pItem = new CParagraphProperty(*m_oParagraphProperty);
|
||||
pItem->m_pMainDocument = document;
|
||||
|
||||
pItem = m_oParagraphProperty = new CParagraphProperty(CParagraphProperty::Merge(*m_oParagraphProperty, prop2));
|
||||
m_arrItems.push_back( pItem );
|
||||
continue;
|
||||
m_oParagraphProperty = dynamic_cast<CParagraphProperty*>(pItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -383,9 +381,21 @@ namespace OOX
|
||||
}
|
||||
else if (L"p" == sName)
|
||||
{
|
||||
int nDepthChild = oReader.GetDepth();
|
||||
|
||||
fromXML(nDepthChild, oReader);
|
||||
WritingElementWithChilds* parent = dynamic_cast<WritingElementWithChilds*>(m_oParent);
|
||||
if (parent)
|
||||
{
|
||||
WritingElement* pItemUpper = new CParagraph(document, parent);
|
||||
if (pItemUpper)
|
||||
{
|
||||
pItemUpper->fromXML(oReader);
|
||||
parent->m_arrItems.push_back(pItemUpper);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int nDepthChild = oReader.GetDepth();
|
||||
fromXML(nDepthChild, oReader);
|
||||
}
|
||||
}
|
||||
if ( pItem )
|
||||
{
|
||||
|
||||
@ -582,7 +582,7 @@ namespace OOX
|
||||
}
|
||||
}
|
||||
}
|
||||
void CParagraphProperty::fromXML(XmlUtils::CXmlLiteReader& oReader)
|
||||
void CParagraphProperty::fromXML(XmlUtils::CXmlLiteReader& oReader/*, bool bEmbedded*/)
|
||||
{
|
||||
if ( oReader.IsEmptyNode() )
|
||||
return;
|
||||
@ -659,15 +659,13 @@ namespace OOX
|
||||
|
||||
if (doc->m_arrSections.empty())
|
||||
{
|
||||
OOX::CDocument::_section section;
|
||||
doc->m_arrSections.push_back(section);
|
||||
doc->m_arrSections.emplace_back();
|
||||
}
|
||||
doc->m_arrSections.back().sect = m_oSectPr.GetPointer();
|
||||
doc->m_arrSections.back().end_elm = doc->m_arrItems.size() + 1; // порядок выше - сначала читаем, потом добавляем
|
||||
|
||||
OOX::CDocument::_section section;
|
||||
section.start_elm = doc->m_arrItems.size() + 1;
|
||||
doc->m_arrSections.push_back(section);
|
||||
doc->m_arrSections.emplace_back();
|
||||
doc->m_arrSections.back().start_elm = doc->m_arrItems.size() + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2391,6 +2391,18 @@ void CDrawingConverter::ConvertShape(PPTX::Logic::SpTreeElem *elem, XmlUtils::CX
|
||||
pShape->nvSpPr.cNvSpPr.txBox = true;
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
nullable_bool hr;
|
||||
XmlMacroReadAttributeBase(oNodeShape, L"o:hr", hr);
|
||||
|
||||
if (hr.IsInit() && *hr)
|
||||
{
|
||||
pSpPr->Geometry.hr.Init();
|
||||
XmlMacroReadAttributeBase(oNodeShape, L"o:hrpct", pSpPr->Geometry.hr->pct);
|
||||
XmlMacroReadAttributeBase(oNodeShape, L"o:hralign", pSpPr->Geometry.hr->align);
|
||||
XmlMacroReadAttributeBase(oNodeShape, L"o:hrnoshade", pSpPr->Geometry.hr->noshade);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
XmlUtils::CXmlNode oNodeG;
|
||||
oNodeG.FromXmlString(strXmlPPTX);
|
||||
@ -2401,6 +2413,14 @@ void CDrawingConverter::ConvertShape(PPTX::Logic::SpTreeElem *elem, XmlUtils::CX
|
||||
PPTX::CCSS oCSSParser;
|
||||
oCSSParser.LoadFromString2(strStyle);
|
||||
|
||||
std::map<std::wstring, std::wstring>::iterator pFind = oCSSParser.m_mapSettings.find(L"visibility");
|
||||
if (oCSSParser.m_mapSettings.end() != pFind)
|
||||
{
|
||||
if (L"hidden" == pFind->second)
|
||||
bHidden = true;
|
||||
else if (L"visible" == pFind->second)
|
||||
bHidden = false;
|
||||
}
|
||||
if (bHidden && false == bIsTop)
|
||||
{
|
||||
pCNvPr->hidden = true;
|
||||
@ -4909,6 +4929,7 @@ void CDrawingConverter::CheckPenShape(PPTX::Logic::SpTreeElem* oElem, XmlUtils::
|
||||
pSpPr->ln->w = size;
|
||||
pPPTShape->m_bIsStroked = true;
|
||||
}
|
||||
|
||||
XmlUtils::CXmlNode oNodeStroke = oNode.ReadNode(L"v:stroke");
|
||||
if (oNodeStroke.IsValid())
|
||||
{
|
||||
@ -5229,7 +5250,7 @@ void CDrawingConverter::SaveObject(LONG lStart, LONG lLength, const std::wstring
|
||||
if (oElem.is<PPTX::Logic::Pic>())
|
||||
{
|
||||
PPTX::Logic::Pic& oPic = oElem.as<PPTX::Logic::Pic>();
|
||||
if(oPic.oleObject.IsInit())
|
||||
if (oPic.oleObject.IsInit())
|
||||
{
|
||||
bOle = oPic.oleObject->isValid();
|
||||
if (oPic.oleObject->m_oDxaOrig.IsInit() == false)
|
||||
@ -5246,11 +5267,20 @@ void CDrawingConverter::SaveObject(LONG lStart, LONG lLength, const std::wstring
|
||||
if (oElem.is<PPTX::Logic::Shape>())
|
||||
{
|
||||
PPTX::Logic::Shape& oShape = oElem.as<PPTX::Logic::Shape>();
|
||||
if(oShape.signatureLine.IsInit())
|
||||
if (oShape.signatureLine.IsInit())
|
||||
{
|
||||
bSignatureLine = true;
|
||||
}
|
||||
}
|
||||
bool bHorizontalRule = false;
|
||||
if (oElem.is<PPTX::Logic::Shape>())
|
||||
{
|
||||
PPTX::Logic::Shape& oShape = oElem.as<PPTX::Logic::Shape>();
|
||||
if (oShape.spPr.Geometry.hr.IsInit())
|
||||
{
|
||||
bHorizontalRule = true;
|
||||
}
|
||||
}
|
||||
NSBinPptxRW::CXmlWriter oXmlWriter(m_pBinaryReader->m_nDocumentType);
|
||||
|
||||
oXmlWriter.m_lObjectIdVML = m_pXmlWriter->m_lObjectIdVML;
|
||||
@ -5263,16 +5293,22 @@ void CDrawingConverter::SaveObject(LONG lStart, LONG lLength, const std::wstring
|
||||
m_pOOXToVMLRenderer = new COOXToVMLGeometry();
|
||||
oXmlWriter.m_pOOXToVMLRenderer = m_pOOXToVMLRenderer;
|
||||
|
||||
if(bOle)
|
||||
if (bOle)
|
||||
{
|
||||
ConvertPicVML(oElem, bsMainProps, oXmlWriter);
|
||||
}
|
||||
else if(bSignatureLine)
|
||||
else if (bSignatureLine)
|
||||
{
|
||||
oXmlWriter.WriteString(L"<w:pict>");
|
||||
ConvertShapeVML(oElem, bsMainProps, oXmlWriter, true);
|
||||
oXmlWriter.WriteString(L"</w:pict>");
|
||||
}
|
||||
else if (bHorizontalRule)
|
||||
{
|
||||
oXmlWriter.WriteString(L"<w:pict>");
|
||||
ConvertShapeVML(oElem, bsMainProps, oXmlWriter);
|
||||
oXmlWriter.WriteString(L"</w:pict>");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
@ -187,12 +187,55 @@ namespace PPTX
|
||||
{
|
||||
if (m_geometry.is_init())
|
||||
m_geometry->toPPTY(pWriter);
|
||||
if (hr.is_init())
|
||||
hr->toPPTY(pWriter);
|
||||
}
|
||||
void HorizontalRule::toPPTY(NSBinPptxRW::CBinaryFileWriter* pWriter) const
|
||||
{
|
||||
pWriter->StartRecord(GEOMETRY_TYPE_HORIZONTALRULE);
|
||||
|
||||
pWriter->WriteBYTE(NSBinPptxRW::g_nodeAttributeStart);
|
||||
pWriter->WriteBool2(0, noshade);
|
||||
pWriter->WriteString2(1, align);
|
||||
pWriter->WriteDoubleReal2(1, pct);
|
||||
pWriter->WriteBYTE(NSBinPptxRW::g_nodeAttributeEnd);
|
||||
pWriter->EndRecord();
|
||||
}
|
||||
void HorizontalRule::fromPPTY(NSBinPptxRW::CBinaryFileReader* pReader)
|
||||
{
|
||||
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:
|
||||
{
|
||||
noshade = pReader->GetBool();
|
||||
}break;
|
||||
case 1:
|
||||
{
|
||||
align = pReader->GetString2();
|
||||
}break;
|
||||
case 2:
|
||||
{
|
||||
pct = pReader->GetDoubleReal();
|
||||
}break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
pReader->Seek(_end_rec);
|
||||
}
|
||||
void Geometry::fromPPTY(NSBinPptxRW::CBinaryFileReader* pReader)
|
||||
{
|
||||
LONG _end_rec = pReader->GetPos() + pReader->GetRecordSize() + 4;
|
||||
|
||||
if (pReader->GetPos() < _end_rec)
|
||||
while (pReader->GetPos() < _end_rec)
|
||||
{
|
||||
BYTE _t = pReader->GetUChar();
|
||||
|
||||
@ -452,6 +495,13 @@ namespace PPTX
|
||||
|
||||
m_geometry.reset(pGeom);
|
||||
}
|
||||
else if (GEOMETRY_TYPE_HORIZONTALRULE == _t)
|
||||
{
|
||||
hr.Init();
|
||||
hr->fromPPTY(pReader);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
pReader->Seek(_end_rec);
|
||||
|
||||
@ -30,8 +30,6 @@
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef PPTX_LOGIC_GEOMETRY_INCLUDE_H_
|
||||
#define PPTX_LOGIC_GEOMETRY_INCLUDE_H_
|
||||
|
||||
#include "./../WrapperWritingElement.h"
|
||||
#include "PrstGeom.h"
|
||||
@ -41,6 +39,17 @@ namespace PPTX
|
||||
{
|
||||
namespace Logic
|
||||
{
|
||||
class HorizontalRule
|
||||
{
|
||||
public:
|
||||
virtual void toPPTY(NSBinPptxRW::CBinaryFileWriter* pWriter) const;
|
||||
virtual void fromPPTY(NSBinPptxRW::CBinaryFileReader* pReader);
|
||||
|
||||
HorizontalRule() {}
|
||||
nullable_bool noshade;
|
||||
nullable_double pct;
|
||||
nullable_string align;
|
||||
};
|
||||
class Geometry : public WrapperWritingElement
|
||||
{
|
||||
public:
|
||||
@ -69,6 +78,7 @@ namespace PPTX
|
||||
|
||||
smart_ptr<WrapperWritingElement> m_geometry;
|
||||
|
||||
nullable<HorizontalRule> hr;
|
||||
protected:
|
||||
virtual void FillParentPointersForChilds();
|
||||
|
||||
@ -78,5 +88,3 @@ namespace PPTX
|
||||
};
|
||||
} // namespace Logic
|
||||
} // namespace PPTX
|
||||
|
||||
#endif // PPTX_LOGIC_GEOMETRY_INCLUDE_H_
|
||||
|
||||
@ -857,7 +857,6 @@ namespace PPTX
|
||||
pWriter->WriteAttribute(L"from", XmlUtils::ToString(pWriter->m_dX, L"%.1lf") + L"pt," + XmlUtils::ToString(pWriter->m_dY, L"%.1lf") + L"pt");
|
||||
pWriter->WriteAttribute(L"to", XmlUtils::ToString(pWriter->m_dX + pWriter->m_dWidth, L"%.1lf") + L"pt," + XmlUtils::ToString(pWriter->m_dY + pWriter->m_dHeight, L"%.1lf") + L"pt");
|
||||
}
|
||||
|
||||
if (false == pWriter->m_strAttributesMain.empty())
|
||||
{
|
||||
pWriter->WriteString(pWriter->m_strAttributesMain);
|
||||
@ -867,6 +866,13 @@ namespace PPTX
|
||||
pWriter->WriteString(strFillAttr);
|
||||
pWriter->WriteString(strStrokeAttr);
|
||||
|
||||
if (spPr.Geometry.hr.IsInit())
|
||||
{
|
||||
pWriter->WriteAttribute(L"o:hr", L"t");
|
||||
pWriter->WriteAttribute(L"o:hrstd", L"t");
|
||||
pWriter->WriteAttribute(L"o:hralign", spPr.Geometry.hr->align);
|
||||
pWriter->WriteAttribute(L"o:hrpct", spPr.Geometry.hr->pct);
|
||||
}
|
||||
pWriter->EndAttributes();
|
||||
|
||||
if (false == strTextRect.empty())
|
||||
|
||||
@ -1225,6 +1225,7 @@ namespace OOX
|
||||
}break;
|
||||
case 1:
|
||||
{
|
||||
pReader->Skip(4); // size
|
||||
content = pReader->GetString2();
|
||||
}break;
|
||||
default:
|
||||
|
||||
@ -443,9 +443,10 @@ void embeddings::write(const std::wstring & RootPath)
|
||||
items[i].type == typeControlProps ||
|
||||
items[i].type == typeControl))
|
||||
{
|
||||
size_t pos_off = items[i].outputName.rfind(L"/");
|
||||
size_t pos = items[i].outputName.rfind(L".");
|
||||
|
||||
int pos = items[i].outputName.rfind(L".");
|
||||
std::wstring extension = pos >= 0 ? items[i].outputName.substr(pos + 1) : L"";
|
||||
std::wstring extension = (pos != std::wstring::npos && pos > pos_off) ? items[i].outputName.substr(pos + 1) : L"";
|
||||
|
||||
content_types.add_or_find_default(extension);
|
||||
|
||||
|
||||
@ -160,7 +160,7 @@ void paragraph_format_properties::docx_convert(oox::docx_conversion_context & Co
|
||||
}
|
||||
if (Context.get_rtl()) //может быть он установился от стиля родителя !!
|
||||
{
|
||||
_pPr << L"<w:bidi/>";
|
||||
_pPr << L"<w:bidi w:val=\"1\"/>";
|
||||
}
|
||||
|
||||
odf_reader::list_style_container & list_styles = Context.root()->odf_context().listStyleContainer();
|
||||
@ -233,6 +233,15 @@ void paragraph_format_properties::docx_convert(oox::docx_conversion_context & Co
|
||||
case text_align::End: jc = Context.get_rtl() ? L"start": L"end"; break;
|
||||
}
|
||||
|
||||
if( Context.get_rtl() )
|
||||
{
|
||||
switch(fo_text_align_->get_type())
|
||||
{
|
||||
case text_align::Left: jc = L"right"; break;
|
||||
case text_align::Right: jc = L"left"; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!jc.empty()) CP_XML_NODE(L"w:jc"){CP_XML_ATTR(L"w:val", jc );}
|
||||
}
|
||||
else if (fo_keep_with_next_) //&& Context.get_drop_cap_context().state() != 2
|
||||
|
||||
@ -983,6 +983,11 @@ void OoxConverter::convert(PPTX::Logic::SpPr *oox_spPr, PPTX::Logic::ShapeStyle*
|
||||
convert(prstGeom);
|
||||
convert(custGeom);
|
||||
|
||||
if (oox_spPr->Geometry.hr.IsInit())
|
||||
{
|
||||
odf_context()->drawing_context()->set_horizontal_rule();
|
||||
}
|
||||
|
||||
bool bLine = odf_context()->drawing_context()->isLineShape();
|
||||
|
||||
if (custGeom && !custGeom->cxnLst.empty() && !odf_context()->drawing_context()->isCustomClosed())
|
||||
|
||||
@ -1064,6 +1064,11 @@ namespace Oox2Odf
|
||||
odf_context()->drawing_context()->set_no_fill();
|
||||
odf_context()->drawing_context()->end_area_properties();
|
||||
}
|
||||
|
||||
if (vml_common->m_oHr.IsInit() && (*vml_common->m_oHr))
|
||||
{
|
||||
odf_context()->drawing_context()->set_horizontal_rule();
|
||||
}
|
||||
}
|
||||
void OoxConverter::convert(OOX::Vml::CGroup *vml_group)
|
||||
{
|
||||
|
||||
@ -2336,6 +2336,18 @@ void odf_drawing_context::get_size( _CP_OPT(double) & width_pt, _CP_OPT(double)
|
||||
height_pt = impl_->anchor_settings_.svg_height_->get_value_unit(length::pt);
|
||||
}
|
||||
}
|
||||
void odf_drawing_context::set_horizontal_rule()
|
||||
{
|
||||
//if (!impl_->current_graphic_properties) return;
|
||||
//impl_->current_graphic_properties->common_draw_rel_size_attlist_.style_rel_width_ = odf_types::percent(100);
|
||||
|
||||
draw_base* draw = dynamic_cast<draw_base*>(impl_->current_level_.back().elm.get());
|
||||
|
||||
if (draw)
|
||||
{
|
||||
draw->common_draw_attlists_.rel_size_.style_rel_width_ = odf_types::percent(100);
|
||||
}
|
||||
}
|
||||
void odf_drawing_context::set_size( _CP_OPT(double) & width_pt, _CP_OPT(double) & height_pt, bool reset_always)
|
||||
{
|
||||
impl_->current_drawing_state_.cx_ = width_pt;
|
||||
|
||||
@ -227,6 +227,8 @@ public:
|
||||
|
||||
void get_size ( _CP_OPT(double) & width_pt, _CP_OPT(double) & height_pt);
|
||||
void set_size ( _CP_OPT(double) & width_pt, _CP_OPT(double) & height_pt, bool reset_always = false);
|
||||
|
||||
void set_horizontal_rule();
|
||||
|
||||
void set_name (const std::wstring & name);
|
||||
void set_description (const std::wstring & descr);
|
||||
|
||||
@ -155,11 +155,11 @@ namespace utils//////////////////////////////////////////// ОБЩАЯ хрен
|
||||
{
|
||||
nDate = boost::lexical_cast<__int64>(oox_date_time);
|
||||
}
|
||||
|
||||
bool bPT = (nDate < 1);
|
||||
std::wstring sDate, sTime;
|
||||
if (dTime > 0)
|
||||
{
|
||||
sTime = convert_time(dTime, false);
|
||||
sTime = convert_time(dTime, bPT);
|
||||
}
|
||||
if (nDate > 0)
|
||||
{
|
||||
@ -177,7 +177,14 @@ namespace utils//////////////////////////////////////////// ОБЩАЯ хрен
|
||||
}
|
||||
else
|
||||
{
|
||||
odf_date_time = sDate + (sTime.empty() ? L"" : L"T" + sTime);
|
||||
if (bPT)
|
||||
{
|
||||
odf_date_time = L"PT" + sTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
odf_date_time = sDate + (sTime.empty() ? L"" : L"T" + sTime);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -416,7 +416,49 @@ PdfWriter::CObjectBase* DictToCDictObject2(Object* obj, PdfWriter::CDocument* pD
|
||||
for (int nIndex = 0; nIndex < obj->dictGetLength(); ++nIndex)
|
||||
{
|
||||
char* chKey = obj->dictGetKey(nIndex);
|
||||
obj->dictGetValNF(nIndex, &oTemp);
|
||||
if (strcmp("Resources", chKey) == 0)
|
||||
{
|
||||
Ref oResourcesRef = { -1, -1 };
|
||||
if (obj->dictGetValNF(nIndex, &oTemp)->isRef())
|
||||
oResourcesRef = oTemp.getRef();
|
||||
oTemp.free();
|
||||
|
||||
PdfWriter::CObjectBase* pObj = oResourcesRef.num > 0 ? pManager->GetObj(oResourcesRef.num + nStartRefID) : NULL;
|
||||
if (pObj)
|
||||
{
|
||||
pDict->Add(chKey, pObj);
|
||||
pManager->IncRefCount(oResourcesRef.num + nStartRefID);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (obj->dictGetVal(nIndex, &oTemp)->isDict())
|
||||
{
|
||||
PdfWriter::CResourcesDict* pResDict = pDoc->CreateResourcesDict(oResourcesRef.num < 0, false);
|
||||
if (oResourcesRef.num > 0)
|
||||
pManager->AddObj(oResourcesRef.num + nStartRefID, pResDict);
|
||||
pDict->Add(chKey, pResDict);
|
||||
for (int nIndex2 = 0; nIndex2 < oTemp.dictGetLength(); ++nIndex2)
|
||||
{
|
||||
Object oRes;
|
||||
char* chKey2 = oTemp.dictGetKey(nIndex2);
|
||||
oTemp.dictGetValNF(nIndex2, &oRes);
|
||||
pBase = DictToCDictObject2(&oRes, pDoc, xref, pManager, nStartRefID, 0, bUndecodedStream);
|
||||
pResDict->Add(chKey2, pBase);
|
||||
oRes.free();
|
||||
}
|
||||
pResDict->Fix();
|
||||
|
||||
oTemp.free();
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
oTemp.free();
|
||||
obj->dictGetValNF(nIndex, &oTemp);
|
||||
}
|
||||
}
|
||||
else
|
||||
obj->dictGetValNF(nIndex, &oTemp);
|
||||
pBase = DictToCDictObject2(&oTemp, pDoc, xref, pManager, nStartRefID, 0, bUndecodedStream);
|
||||
pDict->Add(chKey, pBase);
|
||||
oTemp.free();
|
||||
@ -470,7 +512,49 @@ PdfWriter::CObjectBase* DictToCDictObject2(Object* obj, PdfWriter::CDocument* pD
|
||||
oTemp.free();
|
||||
continue;
|
||||
}
|
||||
pODict->getValNF(nIndex, &oTemp);
|
||||
else if (strcmp("Resources", chKey) == 0)
|
||||
{
|
||||
Ref oResourcesRef = { -1, -1 };
|
||||
if (pODict->getValNF(nIndex, &oTemp)->isRef())
|
||||
oResourcesRef = oTemp.getRef();
|
||||
oTemp.free();
|
||||
|
||||
PdfWriter::CObjectBase* pObj = oResourcesRef.num > 0 ? pManager->GetObj(oResourcesRef.num + nStartRefID) : NULL;
|
||||
if (pObj)
|
||||
{
|
||||
pDict->Add(chKey, pObj);
|
||||
pManager->IncRefCount(oResourcesRef.num + nStartRefID);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pODict->getVal(nIndex, &oTemp)->isDict())
|
||||
{
|
||||
PdfWriter::CResourcesDict* pResDict = pDoc->CreateResourcesDict(oResourcesRef.num < 0, false);
|
||||
if (oResourcesRef.num > 0)
|
||||
pManager->AddObj(oResourcesRef.num + nStartRefID, pResDict);
|
||||
pDict->Add(chKey, pResDict);
|
||||
for (int nIndex2 = 0; nIndex2 < oTemp.dictGetLength(); ++nIndex2)
|
||||
{
|
||||
Object oRes;
|
||||
char* chKey2 = oTemp.dictGetKey(nIndex2);
|
||||
oTemp.dictGetValNF(nIndex2, &oRes);
|
||||
pBase = DictToCDictObject2(&oRes, pDoc, xref, pManager, nStartRefID, 0, bUndecodedStream);
|
||||
pResDict->Add(chKey2, pBase);
|
||||
oRes.free();
|
||||
}
|
||||
pResDict->Fix();
|
||||
|
||||
oTemp.free();
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
oTemp.free();
|
||||
pODict->getValNF(nIndex, &oTemp);
|
||||
}
|
||||
}
|
||||
else
|
||||
pODict->getValNF(nIndex, &oTemp);
|
||||
pBase = DictToCDictObject2(&oTemp, pDoc, xref, pManager, nStartRefID);
|
||||
pDict->Add(chKey, pBase);
|
||||
oTemp.free();
|
||||
@ -2337,11 +2421,11 @@ bool CPdfEditor::SplitPages(const int* arrPageIndex, unsigned int unLength, PDFD
|
||||
if (oResourcesRef.num > 0)
|
||||
m_mObjManager.AddObj(oResourcesRef.num + nStartRefID, pDict);
|
||||
pPage->Add(chKey, pDict);
|
||||
for (int nIndex = 0; nIndex < oTemp.dictGetLength(); ++nIndex)
|
||||
for (int nIndex2 = 0; nIndex2 < oTemp.dictGetLength(); ++nIndex2)
|
||||
{
|
||||
Object oRes;
|
||||
char* chKey2 = oTemp.dictGetKey(nIndex);
|
||||
oTemp.dictGetValNF(nIndex, &oRes);
|
||||
char* chKey2 = oTemp.dictGetKey(nIndex2);
|
||||
oTemp.dictGetValNF(nIndex2, &oRes);
|
||||
PdfWriter::CObjectBase* pBase = DictToCDictObject2(&oRes, pDoc, xref, &m_mObjManager, nStartRefID);
|
||||
pDict->Add(chKey2, pBase);
|
||||
oRes.free();
|
||||
@ -4051,7 +4135,35 @@ void CPdfEditor::ClearPage()
|
||||
pageObj.free();
|
||||
|
||||
if (m_nMode == Mode::Split || m_nMode == Mode::WriteNew)
|
||||
{
|
||||
PdfWriter::CPage* pPage = pDoc->GetCurPage();
|
||||
auto removeContentObj = [&](PdfWriter::CObjectBase* pObj)
|
||||
{
|
||||
if (pObj->GetType() == PdfWriter::object_type_DICT)
|
||||
{
|
||||
PdfWriter::CObjectBase* pLength = ((PdfWriter::CDictObject*)pObj)->Get("Length");
|
||||
if (pLength)
|
||||
{
|
||||
int nLengthID = m_mObjManager.FindObj(pLength);
|
||||
m_mObjManager.RemoveObj(nLengthID);
|
||||
}
|
||||
}
|
||||
int nObjID = m_mObjManager.FindObj(pObj);
|
||||
m_mObjManager.RemoveObj(nObjID);
|
||||
};
|
||||
|
||||
PdfWriter::CObjectBase* pObjContents = pPage->Get("Contents");
|
||||
if (pObjContents && pObjContents->GetType() == PdfWriter::object_type_ARRAY)
|
||||
{
|
||||
PdfWriter::CArrayObject* pContents = (PdfWriter::CArrayObject*)pObjContents;
|
||||
for (int i = 0; i < pContents->GetCount(); ++i)
|
||||
removeContentObj(pContents->Get(i));
|
||||
}
|
||||
else if (pObjContents)
|
||||
removeContentObj(pObjContents);
|
||||
|
||||
pDoc->ClearPageFull();
|
||||
}
|
||||
else
|
||||
pDoc->ClearPage();
|
||||
|
||||
|
||||
@ -1849,7 +1849,7 @@ namespace PdfWriter
|
||||
|
||||
}
|
||||
|
||||
if (!m_pAppearance)
|
||||
if (!m_pAppearance && !bNoAP)
|
||||
{
|
||||
m_pAppearance = new CAnnotAppearance(m_pXref, this);
|
||||
CObjectBase* pAP = Get("AP");
|
||||
@ -1882,6 +1882,8 @@ namespace PdfWriter
|
||||
|
||||
if (bNoAP)
|
||||
{
|
||||
RemoveAP();
|
||||
|
||||
if (pForm)
|
||||
{
|
||||
CheckMK();
|
||||
|
||||
@ -521,6 +521,7 @@ void ApplyRedactToGray(const std::vector<double>& arrQuadPoints, BYTE* pImage, i
|
||||
RedactOutputDev::RedactOutputDev(CPdfWriter* pRenderer, CObjectsManager* pObjMng, int nStartRefID)
|
||||
{
|
||||
m_pXref = NULL;
|
||||
m_pResources = NULL;
|
||||
|
||||
m_pRenderer = pRenderer;
|
||||
m_mObjManager = pObjMng;
|
||||
@ -565,6 +566,32 @@ void RedactOutputDev::startPage(int nPageIndex, GfxState *pGState)
|
||||
m_pPage = m_pDoc->GetEditPage(nPageIndex);
|
||||
m_pRenderer->EditPage(m_pPage);
|
||||
m_pDoc->SetCurPage(m_pPage);
|
||||
|
||||
auto removeContentObj = [&](PdfWriter::CObjectBase* pObj)
|
||||
{
|
||||
if (pObj->GetType() == PdfWriter::object_type_DICT)
|
||||
{
|
||||
PdfWriter::CObjectBase* pLength = ((PdfWriter::CDictObject*)pObj)->Get("Length");
|
||||
if (pLength)
|
||||
{
|
||||
int nLengthID = m_mObjManager->FindObj(pLength);
|
||||
m_mObjManager->RemoveObj(nLengthID);
|
||||
}
|
||||
}
|
||||
int nObjID = m_mObjManager->FindObj(pObj);
|
||||
m_mObjManager->RemoveObj(nObjID);
|
||||
};
|
||||
|
||||
PdfWriter::CObjectBase* pObjContents = m_pPage->Get("Contents");
|
||||
if (pObjContents && pObjContents->GetType() == PdfWriter::object_type_ARRAY)
|
||||
{
|
||||
PdfWriter::CArrayObject* pContents = (PdfWriter::CArrayObject*)pObjContents;
|
||||
for (int i = 0; i < pContents->GetCount(); ++i)
|
||||
removeContentObj(pContents->Get(i));
|
||||
}
|
||||
else if (pObjContents)
|
||||
removeContentObj(pObjContents);
|
||||
|
||||
m_pDoc->ClearPageFull();
|
||||
}
|
||||
void RedactOutputDev::endPage()
|
||||
@ -1374,11 +1401,16 @@ void RedactOutputDev::drawForm(GfxState *pGState, Gfx *gfx, Ref id, const char*
|
||||
pObj = pOrigForm->Get("Matrix");
|
||||
if (pObj)
|
||||
pNewForm->Add("Matrix", pObj->Copy());
|
||||
|
||||
PdfWriter::CResourcesDict* pNewResources = NULL;
|
||||
pObj = pOrigForm->Get("Resources");
|
||||
if (pObj)
|
||||
{
|
||||
pNewForm->Add("Resources", pObj->Copy());
|
||||
pNewResources = dynamic_cast<CResourcesDict*>(pNewForm->Get("Resources"));
|
||||
}
|
||||
|
||||
PdfWriter::CResourcesDict* pResources = GetResources(gfx);
|
||||
PdfWriter::CResourcesDict* pResources = GetResources(gfx, pNewForm);
|
||||
if (pResources)
|
||||
name = pResources->GetXObjectName(pNewForm);
|
||||
|
||||
@ -1391,6 +1423,7 @@ void RedactOutputDev::drawForm(GfxState *pGState, Gfx *gfx, Ref id, const char*
|
||||
RedactOutputDev* pFormOutputDev = new RedactOutputDev(m_pRenderer, m_mObjManager, m_nStartRefID);
|
||||
pFormOutputDev->NewPDF(m_pXref);
|
||||
pFormOutputDev->m_pPage = pFakePage;
|
||||
pFormOutputDev->m_pResources = pNewResources;
|
||||
std::vector<double> arrFormQuadPoints;
|
||||
double dInvMatrix[6] = { 1, 0, 0, 1, 0, 0 };
|
||||
InvertMatrix(m_arrMatrix, dInvMatrix);
|
||||
@ -1886,8 +1919,11 @@ CObjectBase* RedactOutputDev::CreateImage(Gfx *gfx, int nWidth, int nHeight, uns
|
||||
|
||||
return pObj;
|
||||
}
|
||||
CResourcesDict* RedactOutputDev::GetResources(Gfx *gfx)
|
||||
CResourcesDict* RedactOutputDev::GetResources(Gfx *gfx, CDictObject* pNewForm)
|
||||
{
|
||||
if (m_pResources)
|
||||
return m_pResources;
|
||||
|
||||
PdfWriter::CResourcesDict* pResources = NULL;
|
||||
Object* pContent = gfx->getTopContentStreamStack();
|
||||
if (pContent && pContent->isRef())
|
||||
@ -1901,7 +1937,7 @@ CResourcesDict* RedactOutputDev::GetResources(Gfx *gfx)
|
||||
if (!pResources)
|
||||
{
|
||||
pResources = new PdfWriter::CResourcesDict(NULL, true, false);
|
||||
pDictForm->Add("Resources", pResources);
|
||||
(pNewForm ? pNewForm : pDictForm)->Add("Resources", pResources);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,11 +201,12 @@ namespace PdfWriter
|
||||
void DoStateOp();
|
||||
void DrawXObject(const char* name);
|
||||
CObjectBase* CreateImage(Gfx *gfx, int nWidth, int nHeight, unsigned int nFilter, int nBPC, const char* sCS);
|
||||
CResourcesDict* GetResources(Gfx *gfx);
|
||||
CResourcesDict* GetResources(Gfx *gfx, CDictObject* pNewForm = NULL);
|
||||
|
||||
XRef* m_pXref;
|
||||
std::vector<double> m_arrQuadPoints;
|
||||
Aggplus::CGraphicsPath m_oPathRedact;
|
||||
CResourcesDict* m_pResources;
|
||||
|
||||
CPdfWriter* m_pRenderer;
|
||||
CObjectsManager* m_mObjManager;
|
||||
|
||||
@ -67,6 +67,19 @@ namespace PdfWriter
|
||||
pProcset->Add(new CNameObject("ImageI"));
|
||||
}
|
||||
}
|
||||
CObjectBase* CResourcesDict::Copy(CObjectBase* pOut) const
|
||||
{
|
||||
CResourcesDict* pDict = pOut && pOut->GetType() == object_type_DICT ? dynamic_cast<CResourcesDict*>(pOut) : new CResourcesDict(NULL, true, false);
|
||||
if (!pDict)
|
||||
return NULL;
|
||||
|
||||
for (auto const &oIter : m_mList)
|
||||
pDict->Add(oIter.first, oIter.second->Copy());
|
||||
|
||||
pDict->Fix();
|
||||
|
||||
return pDict;
|
||||
}
|
||||
const char* CResourcesDict::GetFontName(CFontDict* pFont)
|
||||
{
|
||||
if (!m_pFonts)
|
||||
|
||||
@ -46,6 +46,8 @@ namespace PdfWriter
|
||||
public:
|
||||
CResourcesDict(CXref* pXref, bool bInline, bool bProcSet);
|
||||
|
||||
virtual CObjectBase* Copy(CObjectBase* pOut) const override;
|
||||
|
||||
const char* GetFontName(CFontDict* pFont);
|
||||
const char* GetExtGrStateName(CExtGrState* pState);
|
||||
const char* GetXObjectName(CObjectBase* pXObject);
|
||||
|
||||
@ -46,6 +46,60 @@
|
||||
|
||||
namespace Txt2Docx
|
||||
{
|
||||
namespace
|
||||
{
|
||||
bool isEmoji(const std::string& utf8Char)
|
||||
{
|
||||
if (utf8Char.empty()) return false;
|
||||
|
||||
unsigned char c = utf8Char[0];
|
||||
uint32_t codePoint = 0;
|
||||
|
||||
if ((c & 0xF8) == 0xF0 && utf8Char.length() >= 4)
|
||||
{
|
||||
codePoint = ((utf8Char[0] & 0x07) << 18) |
|
||||
((utf8Char[1] & 0x3F) << 12) |
|
||||
((utf8Char[2] & 0x3F) << 6) |
|
||||
(utf8Char[3] & 0x3F);
|
||||
}
|
||||
else if ((c & 0xF0) == 0xE0 && utf8Char.length() >= 3)
|
||||
{
|
||||
codePoint = ((utf8Char[0] & 0x0F) << 12) |
|
||||
((utf8Char[1] & 0x3F) << 6) |
|
||||
(utf8Char[2] & 0x3F);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (codePoint >= 0x1F300 && codePoint <= 0x1F9FF) ||
|
||||
(codePoint >= 0x2600 && codePoint <= 0x27BF) ||
|
||||
(codePoint >= 0x2B00 && codePoint <= 0x2BFF) ||
|
||||
(codePoint >= 0xFE00 && codePoint <= 0xFE0F) ||
|
||||
(codePoint >= 0x1F900 && codePoint <= 0x1F9FF) ||
|
||||
codePoint == 0x00A9 || codePoint == 0x00AE;
|
||||
}
|
||||
|
||||
std::string escapeXml(const std::string& text)
|
||||
{
|
||||
std::string result;
|
||||
result.reserve(text.length() * 2);
|
||||
for (char ch : text)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case '&': result += "&"; break;
|
||||
case '<': result += "<"; break;
|
||||
case '>': result += ">"; break;
|
||||
case '"': result += """; break;
|
||||
case '\'': result += "'"; break;
|
||||
default: result += ch; break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
class Converter_Impl
|
||||
{
|
||||
public:
|
||||
@ -158,8 +212,8 @@ namespace Txt2Docx
|
||||
void Converter::write(NSStringUtils::CStringBuilderA &stringWriter)
|
||||
{
|
||||
const char* fontName = "Courier New";
|
||||
const char* emojiFontName = "Segoe UI Emoji";
|
||||
const char* defaultSpacing = "<w:spacing w:after=\"0\" w:line=\"240\" w:lineRule=\"auto\"/>";
|
||||
|
||||
for (const std::string &lineRaw : converter_->m_inputFile.m_listContentutf8)
|
||||
{
|
||||
std::string line = lineRaw;
|
||||
@ -176,32 +230,86 @@ namespace Txt2Docx
|
||||
stringWriter.WriteString(fontName);
|
||||
stringWriter.WriteString("\"/></w:rPr></w:pPr>");
|
||||
|
||||
size_t start = 0;
|
||||
while (true)
|
||||
size_t i = 0;
|
||||
while (i < line.length())
|
||||
{
|
||||
size_t pos = line.find('\x09', start);
|
||||
std::string segment = (pos == std::string::npos) ? line.substr(start) : line.substr(start, pos - start);
|
||||
unsigned char c = line[i];
|
||||
|
||||
if (!segment.empty())
|
||||
if ((c & 0xF0) == 0xF0 || (c & 0xE0) == 0xE0)
|
||||
{
|
||||
stringWriter.WriteString("<w:r><w:rPr><w:rFonts w:ascii=\"");
|
||||
stringWriter.WriteString(fontName);
|
||||
stringWriter.WriteString("\" w:hAnsi=\"");
|
||||
stringWriter.WriteString(fontName);
|
||||
stringWriter.WriteString("\" w:cs=\"");
|
||||
stringWriter.WriteString(fontName);
|
||||
stringWriter.WriteString("\"/></w:rPr><w:t xml:space=\"preserve\">");
|
||||
stringWriter.WriteString(segment.c_str());
|
||||
stringWriter.WriteString("</w:t></w:r>");
|
||||
int possibleLen = ((c & 0xF0) == 0xF0) ? 4 : 3;
|
||||
|
||||
if (i + possibleLen <= line.length())
|
||||
{
|
||||
std::string possible = line.substr(i, possibleLen);
|
||||
|
||||
if (isEmoji(possible))
|
||||
{
|
||||
stringWriter.WriteString("<w:r><w:rPr><w:rFonts w:ascii=\"");
|
||||
stringWriter.WriteString(emojiFontName);
|
||||
stringWriter.WriteString("\" w:hAnsi=\"");
|
||||
stringWriter.WriteString(emojiFontName);
|
||||
stringWriter.WriteString("\" w:cs=\"");
|
||||
stringWriter.WriteString(emojiFontName);
|
||||
stringWriter.WriteString("\"/></w:rPr><w:t xml:space=\"preserve\">");
|
||||
stringWriter.WriteString(possible.c_str());
|
||||
stringWriter.WriteString("</w:t></w:r>");
|
||||
|
||||
i += possibleLen;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pos == std::string::npos)
|
||||
break;
|
||||
size_t textStart = i;
|
||||
while (i < line.length())
|
||||
{
|
||||
unsigned char next = line[i];
|
||||
if ((next & 0xF0) == 0xF0 || (next & 0xE0) == 0xE0)
|
||||
{
|
||||
int checkLen = ((next & 0xF0) == 0xF0) ? 4 : 3;
|
||||
if (i + checkLen <= line.length())
|
||||
{
|
||||
std::string check = line.substr(i, checkLen);
|
||||
if (isEmoji(check))
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
stringWriter.WriteString("<w:tab/>");
|
||||
start = pos + 1;
|
||||
std::string textSegment = line.substr(textStart, i - textStart);
|
||||
|
||||
size_t tabStart = 0;
|
||||
while (true)
|
||||
{
|
||||
size_t tabPos = textSegment.find('\x09', tabStart);
|
||||
std::string seg = (tabPos == std::string::npos) ?
|
||||
textSegment.substr(tabStart) :
|
||||
textSegment.substr(tabStart, tabPos - tabStart);
|
||||
|
||||
if (!seg.empty())
|
||||
{
|
||||
std::string escaped = escapeXml(seg);
|
||||
|
||||
stringWriter.WriteString("<w:r><w:rPr><w:rFonts w:ascii=\"");
|
||||
stringWriter.WriteString(fontName);
|
||||
stringWriter.WriteString("\" w:hAnsi=\"");
|
||||
stringWriter.WriteString(fontName);
|
||||
stringWriter.WriteString("\" w:cs=\"");
|
||||
stringWriter.WriteString(fontName);
|
||||
stringWriter.WriteString("\"/></w:rPr><w:t xml:space=\"preserve\">");
|
||||
stringWriter.WriteString(escaped.c_str());
|
||||
stringWriter.WriteString("</w:t></w:r>");
|
||||
}
|
||||
|
||||
if (tabPos == std::string::npos)
|
||||
break;
|
||||
|
||||
stringWriter.WriteString("<w:r><w:tab/></w:r>");
|
||||
tabStart = tabPos + 1;
|
||||
}
|
||||
}
|
||||
|
||||
stringWriter.WriteString("</w:p>");
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,7 +130,7 @@ namespace NSUnicodeConverter
|
||||
|
||||
static std::string fromUnicode(const wchar_t* sInput, const unsigned int& nInputLen, const char* converterName)
|
||||
{
|
||||
if (nInputLen > 0)
|
||||
if (nInputLen <= 0)
|
||||
return "";
|
||||
|
||||
NSString* sEncodingCF = StringAToNSString(std::string(converterName));
|
||||
|
||||
Reference in New Issue
Block a user