Compare commits

...

20 Commits

Author SHA1 Message Date
57c99df412 Merge pull request 'Fix bug 80646' (#724) from fix/bug-80646 into release/v9.4.0
Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/core/pulls/724
2026-03-16 12:49:48 +00:00
df86855ccf Fix bug 80646 2026-03-16 14:14:53 +03:00
da769a642b Merge branch hotfix/v9.3.1 into release/v9.4.0 2026-03-12 15:19:51 +00:00
12083ae8c9 Merge pull request 'Fix bugs 75897, 80163' (#722) from fix/pdf-bug into release/v9.4.0
Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/core/pulls/722
2026-03-12 12:29:03 +00:00
6819a41452 Fix bug 75897 2026-03-12 14:06:57 +03:00
5d5732161a Fix bug 80163 2026-03-12 11:11:32 +03:00
9983161e3d Merge branch 'hotfix/v9.3.1' of https://git.onlyoffice.com/ONLYOFFICE/core into hotfix/v9.3.1 2026-03-09 21:14:43 +03:00
33c4b5130e Revert missed file 2026-03-09 21:14:26 +03:00
0101774675 Fix safeUrl method 2026-03-09 13:35:40 +03:00
de9709ea50 Fix fromUnicode on ios 2026-03-09 13:35:02 +03:00
22e7c5bed4 Change download method 2026-03-06 23:25:00 +03:00
573b85932f Merge branch release/v9.3.0 into hotfix/v9.3.1 2026-03-04 09:17:03 +00:00
52f8640b10 Merge pull request 'fix prev' (#707) from fix/fix-bugs into hotfix/v9.3.1
Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/core/pulls/707
2026-03-02 10:46:12 +00:00
8a1a45f403 fix prev 2026-03-02 10:04:34 +03:00
2b46e0251f Merge pull request 'fix for prev binary' (#705) from fix/fix-bugs into hotfix/v9.3.1
Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/core/pulls/705
2026-02-27 13:42:47 +00:00
078a58772c fix for prev binary 2026-02-27 16:37:30 +03:00
d54f0326cd Merge branch release/v9.3.0 into master 2026-02-24 14:07:21 +00:00
7d06219664 Merge branch hotfix/v9.2.1 into master 2025-12-26 16:24:51 +00:00
e936b0e4e7 Merge branch hotfix/v9.2.1 into master 2025-12-25 10:57:58 +00:00
a22f0bfb60 Merge branch hotfix/v9.2.1 into master 2025-12-17 11:33:19 +00:00
14 changed files with 328 additions and 252 deletions

View File

@ -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)){
>>>>>>>

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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);

View File

@ -267,7 +267,7 @@ namespace SimpleTypes
std::wstring CGuid::ToString (bool braces) const
{
std::wstringstream sstream;
sstream << boost::wformat( L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" ) % m_oGUID.a % m_oGUID.b % m_oGUID.c % m_oGUID.d % m_oGUID.e % m_oGUID.f % m_oGUID.g % m_oGUID.h % m_oGUID.i % m_oGUID.j % m_oGUID.k;
sstream << boost::wformat( L"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X" ) % m_oGUID.a % m_oGUID.b % m_oGUID.c % m_oGUID.d % m_oGUID.e % m_oGUID.f % m_oGUID.g % m_oGUID.h % m_oGUID.i % m_oGUID.j % m_oGUID.k;
std::wstring res = (braces ? L"{" : L"") + sstream.str() + (braces ? L"}" : L"");
return res;
}

View File

@ -58,6 +58,7 @@
#include "SrcWriter/GState.h"
#include "SrcWriter/RedactOutputDev.h"
#include "SrcWriter/Image.h"
#include "SrcWriter/Font14.h"
#define AddToObject(oVal)\
{\
@ -4488,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);
}
}
}

View File

@ -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)
{

View File

@ -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);
}

View File

@ -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();

View File

@ -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)
{

View File

@ -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;

View File

@ -104,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)
{
// если фонт не зарегистрирован в ресурсах, тогда регистрируем его

View File

@ -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));