mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-03-23 18:21:41 +08:00
Compare commits
38 Commits
feature/so
...
v9.4.0.28
| Author | SHA1 | Date | |
|---|---|---|---|
| 22bbfa3729 | |||
| b1623b203b | |||
| ca08c74fb4 | |||
| 7d161bda01 | |||
| 57c99df412 | |||
| df86855ccf | |||
| 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>
|
||||
|
||||
@ -958,7 +958,7 @@ void ReadInteractiveFormsFonts(CDrawingFile* pGrFile, int nType)
|
||||
if (pFont)
|
||||
free(pFont);
|
||||
|
||||
if (true)
|
||||
if (false)
|
||||
continue;
|
||||
|
||||
pFont = GetGIDByUnicode(pGrFile, (char*)sFontName.c_str());
|
||||
@ -1353,9 +1353,9 @@ int main(int argc, char* argv[])
|
||||
std::cout << " Unicode " << nPathLength;
|
||||
nPathLength = READ_INT(pGlyphs + i);
|
||||
i += 4;
|
||||
std::cout << " width " << (double)nPathLength / 10000.0;
|
||||
std::cout << "\twidth " << (double)nPathLength / 10000.0;
|
||||
if (nCharX)
|
||||
std::cout << " charX " << (double)nCharX / 10000.0;
|
||||
std::cout << "\tcharX " << (double)nCharX / 10000.0;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
@ -2252,7 +2252,7 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
// SCAN PAGE Fonts
|
||||
if (false)
|
||||
if (true)
|
||||
{
|
||||
SetScanPageFonts(pGrFile, nTestPage);
|
||||
|
||||
|
||||
@ -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())
|
||||
|
||||
@ -736,7 +736,7 @@ namespace PPTX
|
||||
if (m_elem.is_init())
|
||||
m_elem->toXmlWriter(pWriter);
|
||||
}
|
||||
std::wstring SpTreeElem::GetSlicerRequires()
|
||||
std::wstring SpTreeElem::GetRequires()
|
||||
{
|
||||
if (m_elem.IsInit() && m_elem.is<PPTX::Logic::GraphicFrame>())
|
||||
{
|
||||
@ -749,6 +749,10 @@ namespace PPTX
|
||||
{
|
||||
return L"sle15";
|
||||
}
|
||||
else if (oGraphicFrame.chartRec.IsInit() && oGraphicFrame.chartRec->m_bChartEx)
|
||||
{
|
||||
return L"cx4";
|
||||
}
|
||||
}
|
||||
return L"";
|
||||
}
|
||||
|
||||
@ -96,7 +96,7 @@ namespace PPTX
|
||||
smart_ptr<WrapperWritingElement> GetElemAlternative();
|
||||
|
||||
virtual void SetParentPointer(const WrapperWritingElement* pParent);
|
||||
std::wstring GetSlicerRequires();
|
||||
std::wstring GetRequires();
|
||||
|
||||
nullable<OOX::Logic::CBinData> m_binaryData;
|
||||
std::wstring m_sRequires;//from mc:Choice
|
||||
|
||||
@ -1225,6 +1225,7 @@ namespace OOX
|
||||
}break;
|
||||
case 1:
|
||||
{
|
||||
pReader->Skip(4); // size
|
||||
content = pReader->GetString2();
|
||||
}break;
|
||||
default:
|
||||
|
||||
@ -165,7 +165,7 @@ namespace OOX
|
||||
}
|
||||
if(m_oElement.IsInit())
|
||||
{
|
||||
std::wstring sRequires = m_oElement->GetSlicerRequires();
|
||||
std::wstring sRequires = m_oElement->GetRequires();
|
||||
if(L"a14" == sRequires)
|
||||
{
|
||||
writer.WriteString(L"<mc:AlternateContent xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"><mc:Choice xmlns:a14=\"http://schemas.microsoft.com/office/drawing/2010/main\" Requires=\"a14\">");
|
||||
@ -174,14 +174,28 @@ namespace OOX
|
||||
{
|
||||
writer.WriteString(L"<mc:AlternateContent xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"><mc:Choice xmlns:sle15=\"http://schemas.microsoft.com/office/drawing/2012/slicer\" Requires=\"sle15\">");
|
||||
}
|
||||
else if (L"cx4" == sRequires)
|
||||
{
|
||||
writer.WriteString(L"<mc:AlternateContent xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"><mc:Choice xmlns:cx4=\"http://schemas.microsoft.com/office/drawing/2016/5/10/chartex\" Requires=\"cx4\">");
|
||||
}
|
||||
NSBinPptxRW::CXmlWriter oXmlWriter(XMLWRITER_DOC_TYPE_XLSX);
|
||||
|
||||
m_oElement->toXmlWriter(&oXmlWriter);
|
||||
writer.WriteString(oXmlWriter.GetXmlString());
|
||||
|
||||
if(L"a14" == sRequires || L"sle15" == sRequires)
|
||||
if(L"a14" == sRequires || L"sle15" == sRequires || L"cx4" == sRequires)
|
||||
{
|
||||
writer.WriteString(L"</mc:Choice><mc:Fallback xmlns=\"\"><xdr:sp macro=\"\" textlink=\"\"><xdr:nvSpPr><xdr:cNvPr id=\"0\" name=\"\"/><xdr:cNvSpPr><a:spLocks noTextEdit=\"1\"/></xdr:cNvSpPr></xdr:nvSpPr><xdr:spPr><a:xfrm><a:off x=\"0\" y=\"0\"/><a:ext cx=\"0\" cy=\"0\"/></a:xfrm><a:prstGeom prst=\"rect\"><a:avLst/></a:prstGeom><a:solidFill><a:prstClr val=\"white\"/></a:solidFill><a:ln w=\"1\"><a:solidFill><a:prstClr val=\"green\"/></a:solidFill></a:ln></xdr:spPr><xdr:txBody><a:bodyPr vertOverflow=\"clip\" horzOverflow=\"clip\"/><a:lstStyle/><a:p><a:r><a:rPr lang=\"en-US\" sz=\"1100\"/><a:t>This shape represents a table slicer. Table slicers are not supported in this version of Excel.\n\nIf the shape was modified in an earlier version of Excel, or if the workbook was saved in Excel 2007 or earlier, the slicer can't be used.</a:t></a:r></a:p></xdr:txBody></xdr:sp></mc:Fallback></mc:AlternateContent>");
|
||||
std::wstring text;
|
||||
if (L"a14" == sRequires || L"sle15" == sRequires)
|
||||
{
|
||||
text = L"This shape represents a table slicer.Table slicers are not supported in this version of Excel.\n\nIf the shape was modified in an earlier version of Excel, or if the workbook was saved in Excel 2007 or earlier, the slicer can't be used.";
|
||||
}
|
||||
else if (L"cx4" == sRequires)
|
||||
{
|
||||
text = L"This chart isn't available in your version of Excel.\n\nEditing this shape or saving this workbook into a different file format will permanently break the chart.";
|
||||
}
|
||||
writer.WriteString(L"</mc:Choice><mc:Fallback xmlns=\"\"><xdr:sp macro=\"\" textlink=\"\"><xdr:nvSpPr><xdr:cNvPr id=\"0\" name=\"\"/><xdr:cNvSpPr><a:spLocks noTextEdit=\"1\"/></xdr:cNvSpPr></xdr:nvSpPr><xdr:spPr><a:xfrm><a:off x=\"0\" y=\"0\"/><a:ext cx=\"0\" cy=\"0\"/></a:xfrm><a:prstGeom prst=\"rect\"><a:avLst/></a:prstGeom><a:solidFill><a:prstClr val=\"white\"/></a:solidFill><a:ln w=\"1\"><a:solidFill><a:prstClr val=\"green\"/></a:solidFill></a:ln></xdr:spPr><xdr:txBody><a:bodyPr vertOverflow=\"clip\" horzOverflow=\"clip\"/><a:lstStyle/><a:p><a:r><a:rPr lang=\"en-US\" sz=\"1100\"/><a:t>" + text +
|
||||
L"</a:t></a:r></a:p></xdr:txBody></xdr:sp></mc:Fallback></mc:AlternateContent>");
|
||||
}
|
||||
}
|
||||
if (m_oClientData.IsInit())
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -58,6 +58,7 @@
|
||||
#include "SrcWriter/GState.h"
|
||||
#include "SrcWriter/RedactOutputDev.h"
|
||||
#include "SrcWriter/Image.h"
|
||||
#include "SrcWriter/Font14.h"
|
||||
|
||||
#define AddToObject(oVal)\
|
||||
{\
|
||||
@ -416,7 +417,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 +513,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 +2422,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 +4136,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();
|
||||
|
||||
@ -4376,26 +4489,36 @@ void CPdfEditor::ScanAndProcessFonts(PDFDoc* pPDFDocument, XRef* xref, Dict* pRe
|
||||
Ref nFontRef = oFontRef.getRef();
|
||||
if (pFontList->GetFont(&nFontRef, &pFontEntry))
|
||||
{
|
||||
std::map<unsigned int, unsigned int> mCodeToWidth, mCodeToUnicode, mCodeToGID;
|
||||
PdfReader::CollectFontWidths(gfxFont, oFont.getDict(), mCodeToWidth);
|
||||
for (int nIndex = 0; nIndex < pFontEntry.unLenUnicode; ++nIndex)
|
||||
PdfWriter::CDocument* pDoc = m_pWriter->GetDocument();
|
||||
PdfWriter::CFontEmbedded* pFont = pDoc->FindFontEmbedded(wsFileName, 0);
|
||||
if (pFont)
|
||||
{
|
||||
if (pFontEntry.pCodeToUnicode[nIndex])
|
||||
mCodeToUnicode[nIndex] = pFontEntry.pCodeToUnicode[nIndex];
|
||||
pFont->UpdateKey(sFontKey);
|
||||
}
|
||||
for (int nIndex = 0; nIndex < pFontEntry.unLenGID; ++nIndex)
|
||||
else
|
||||
{
|
||||
if (pFontEntry.pCodeToGID[nIndex])
|
||||
mCodeToGID[nIndex] = pFontEntry.pCodeToGID[nIndex];
|
||||
std::map<unsigned int, unsigned int> mCodeToWidth, mCodeToUnicode, mCodeToGID;
|
||||
int nDW = PdfReader::CollectFontWidths(gfxFont, oFont.getDict(), mCodeToWidth);
|
||||
for (int nIndex = 0; nIndex < pFontEntry.unLenUnicode; ++nIndex)
|
||||
{
|
||||
if (pFontEntry.pCodeToUnicode[nIndex])
|
||||
mCodeToUnicode[nIndex] = pFontEntry.pCodeToUnicode[nIndex];
|
||||
}
|
||||
for (int nIndex = 0; nIndex < pFontEntry.unLenGID; ++nIndex)
|
||||
{
|
||||
if (pFontEntry.pCodeToGID[nIndex])
|
||||
mCodeToGID[nIndex] = pFontEntry.pCodeToGID[nIndex];
|
||||
}
|
||||
m_pWriter->AddFont(L"Embedded: " + wsFontName, false, false, wsFileName, 0);
|
||||
PdfWriter::CObjectBase* pObj = m_mObjManager.GetObj(nFontRef.num + nStartRefID);
|
||||
if (!pObj)
|
||||
{
|
||||
pObj = new PdfWriter::CObjectBase();
|
||||
pObj->SetRef(nFontRef.num, nFontRef.gen);
|
||||
}
|
||||
pFont = pDoc->CreateFontEmbedded(wsFileName, 0, sFontKey, static_cast<PdfWriter::EFontType>(gfxFont->getType()), pObj, mCodeToWidth, mCodeToUnicode, mCodeToGID);
|
||||
pFont->SetDW(nDW);
|
||||
}
|
||||
m_pWriter->AddFont(L"Embedded: " + wsFontName, false, false, wsFileName, 0);
|
||||
PdfWriter::CObjectBase* pObj = m_mObjManager.GetObj(nFontRef.num + nStartRefID);
|
||||
if (!pObj)
|
||||
{
|
||||
pObj = new PdfWriter::CObjectBase();
|
||||
pObj->SetRef(nFontRef.num, nFontRef.gen);
|
||||
}
|
||||
m_pWriter->GetDocument()->CreateFontEmbedded(wsFileName, 0, sFontKey, static_cast<PdfWriter::EFontType>(gfxFont->getType()), pObj, mCodeToWidth, mCodeToUnicode, mCodeToGID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -953,8 +953,9 @@ std::map<std::wstring, std::wstring> GetFreeTextFont(PDFDoc* pdfDoc, NSFonts::IF
|
||||
|
||||
return mRes;
|
||||
}
|
||||
void CollectFontWidths(GfxFont* gfxFont, Dict* pFontDict, std::map<unsigned int, unsigned int>& mGIDToWidth)
|
||||
int CollectFontWidths(GfxFont* gfxFont, Dict* pFontDict, std::map<unsigned int, unsigned int>& mGIDToWidth)
|
||||
{
|
||||
int nDefaultWidth = 1000;
|
||||
// Пытаемся получить ширины из словаря Widths
|
||||
Object oWidths;
|
||||
if (pFontDict->lookup("Widths", &oWidths)->isArray())
|
||||
@ -988,7 +989,6 @@ void CollectFontWidths(GfxFont* gfxFont, Dict* pFontDict, std::map<unsigned int,
|
||||
{
|
||||
// Получаем DW (default width)
|
||||
Object oDW;
|
||||
int nDefaultWidth = 1000;
|
||||
if (oCIDFont.dictLookup("DW", &oDW)->isInt())
|
||||
nDefaultWidth = oDW.getInt();
|
||||
oDW.free();
|
||||
@ -1063,6 +1063,8 @@ void CollectFontWidths(GfxFont* gfxFont, Dict* pFontDict, std::map<unsigned int,
|
||||
oCIDFont.free();
|
||||
}
|
||||
oDescendantFonts.free();
|
||||
|
||||
return nDefaultWidth;
|
||||
}
|
||||
void CheckFontStylePDF(std::wstring& sName, bool& bBold, bool& bItalic)
|
||||
{
|
||||
|
||||
@ -64,7 +64,7 @@ bool GetFontFromAP(PDFDoc* pdfDoc, AcroFormField* pField, Object* oFontRef, std:
|
||||
std::vector<CAnnotFontInfo> GetAnnotFontInfos(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList* pFontList, Object* oAnnotRef);
|
||||
std::map<std::wstring, std::wstring> GetFreeTextFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList* pFontList, Object* oAnnotRef, std::vector<CAnnotMarkup::CFontData*>& arrRC);
|
||||
bool FindFonts(Object* oStream, int nDepth, Object* oResFonts);
|
||||
void CollectFontWidths(GfxFont* gfxFont, Dict* pFontDict, std::map<unsigned int, unsigned int>& mGIDToWidth);
|
||||
int CollectFontWidths(GfxFont* gfxFont, Dict* pFontDict, std::map<unsigned int, unsigned int>& mGIDToWidth);
|
||||
void CheckFontStylePDF(std::wstring& sName, bool& bBold, bool& bItalic);
|
||||
bool EraseSubsetTag(std::wstring& sFontName);
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -106,6 +106,7 @@ namespace PdfWriter
|
||||
bool CFontEmbedded::LoadFont(const std::string& sFontKey, EFontType eFontType, CObjectBase* pObj,
|
||||
const std::map<unsigned int, unsigned int>& mCodeToWidth, const std::map<unsigned int, unsigned int>& mCodeToUnicode, const std::map<unsigned int, unsigned int>& mCodeToGID)
|
||||
{
|
||||
m_unDW = 1000;
|
||||
m_sFontKey = sFontKey;
|
||||
m_eFontType = eFontType;
|
||||
m_pObj = pObj;
|
||||
@ -122,7 +123,7 @@ namespace PdfWriter
|
||||
if (it != m_mCodeToWidth.end())
|
||||
return it->second;
|
||||
|
||||
return 0;
|
||||
return m_unDW;
|
||||
}
|
||||
unsigned int CFontEmbedded::EncodeUnicode(const unsigned int& unGID, const unsigned int& unUnicode)
|
||||
{
|
||||
|
||||
@ -75,8 +75,10 @@ namespace PdfWriter
|
||||
CObjectBase* GetObj2();
|
||||
const char* GetFontKey() const { return m_sFontKey.c_str(); }
|
||||
void UpdateKey(const std::string& sFontKey) { m_sFontKey = sFontKey; }
|
||||
void SetDW(unsigned int unDW) { m_unDW = unDW; }
|
||||
|
||||
private:
|
||||
unsigned int m_unDW;
|
||||
std::string m_sFontKey;
|
||||
EFontType m_eFontType;
|
||||
CObjectBase* m_pObj;
|
||||
|
||||
@ -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)
|
||||
@ -91,7 +104,16 @@ namespace PdfWriter
|
||||
}
|
||||
}
|
||||
|
||||
const char *sKey = m_pFonts->GetKey(pEmbedded ? pEmbedded->GetObj2() : pFont);
|
||||
const char *sKey = NULL;
|
||||
if (pEmbedded)
|
||||
{
|
||||
CObjectBase* pObj1 = pEmbedded->GetObj2();
|
||||
CObjectBase* pObj2 = m_pFonts->Get(pEmbedded->GetFontKey());
|
||||
if (pObj1 && pObj2 && pObj1->GetType() == object_type_UNKNOWN && pObj1->GetObjId() == pObj2->GetObjId())
|
||||
sKey = pEmbedded->GetFontKey();
|
||||
}
|
||||
if (!sKey)
|
||||
sKey = m_pFonts->GetKey(pEmbedded ? pEmbedded->GetObj2() : pFont);
|
||||
if (!sKey)
|
||||
{
|
||||
// если фонт не зарегистрирован в ресурсах, тогда регистрируем его
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -656,7 +656,7 @@ GBool XRef::readXRefTable(GFileOffset *pos, int offset, XRefPosSet *posSet) {
|
||||
// get the 'Prev' pointer
|
||||
//~ this can be a 64-bit int (?)
|
||||
obj.getDict()->lookupNF("Prev", &obj2);
|
||||
if (obj2.isInt()) {
|
||||
if (obj2.isInt() && obj2.getInt() != 0) {
|
||||
*pos = (GFileOffset)(Guint)obj2.getInt();
|
||||
more = gTrue;
|
||||
} else if (obj2.isRef()) {
|
||||
|
||||
@ -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