From 73b61a91c751ffcbe642572e7dfb46a7e42ff2b5 Mon Sep 17 00:00:00 2001 From: Yingfang Date: Thu, 5 Dec 2024 16:31:43 +0800 Subject: [PATCH 1/5] add bold support for cjk --- platform/darwin/src/local_glyph_rasterizer.mm | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/platform/darwin/src/local_glyph_rasterizer.mm b/platform/darwin/src/local_glyph_rasterizer.mm index 889b1daaadf..39fd6d8c741 100644 --- a/platform/darwin/src/local_glyph_rasterizer.mm +++ b/platform/darwin/src/local_glyph_rasterizer.mm @@ -191,16 +191,29 @@ CFDictionaryRefHandle attributes( @param font The font to apply to the codepoint. @param metrics Upon return, the metrics match the font’s metrics for the glyph representing the codepoint. + @param isBold use kCTFontBoldTrait if it is true. @returns An image containing the glyph. */ -PremultipliedImage drawGlyphBitmap(GlyphID glyphID, CTFontRef font, GlyphMetrics& metrics) { +PremultipliedImage drawGlyphBitmap(GlyphID glyphID, CTFontRef font, GlyphMetrics& metrics, BOOL isBold) { CFStringRefHandle string(CFStringCreateWithCharacters(NULL, reinterpret_cast(&glyphID), 1)); if (!string) { throw std::runtime_error("Unable to create string from codepoint"); } + // Can't use CTFontRefHandle + // because the boldFont will be released after it is out of the isBold condition + CTFontRef boldFont = NULL; + if (isBold) + { + // Create a bold variant of the font + boldFont = CTFontCreateCopyWithSymbolicTraits(font, 0.0, NULL, kCTFontBoldTrait, kCTFontBoldTrait); + if (!boldFont) { + throw std::runtime_error("Unable to create bold font"); + } + } + CFStringRef keys[] = { kCTFontAttributeName }; - CFTypeRef values[] = { font }; + CFTypeRef values[] = { boldFont ? boldFont : font }; CFDictionaryRefHandle attributes( CFDictionaryCreate(kCFAllocatorDefault, (const void**)&keys, @@ -266,6 +279,11 @@ CGContextHandle context(CGBitmapContextCreate( CTLineDraw(*line, *context); + // Release the bold font if it was created + if (boldFont) { + CFRelease(boldFont); + } + return rgbaBitmap; } @@ -288,8 +306,16 @@ CGContextHandle context(CGBitmapContextCreate( } manufacturedGlyph.id = glyphID; + BOOL isBold = NO; + for (auto& fontName : fontStack) { + std::string lowercaseFont = platform::lowercase(fontName); + if (lowercaseFont.find("bold") != std::string::npos) { + isBold = YES; + break; + } + } - PremultipliedImage rgbaBitmap = drawGlyphBitmap(glyphID, *font, manufacturedGlyph.metrics); + PremultipliedImage rgbaBitmap = drawGlyphBitmap(glyphID, *font, manufacturedGlyph.metrics, isBold); Size size(manufacturedGlyph.metrics.width, manufacturedGlyph.metrics.height); // Copy alpha values from RGBA bitmap into the AlphaImage output From 0b94b4c16b1e62bf4f00acbf893289606459065e Mon Sep 17 00:00:00 2001 From: Bart Louwers Date: Fri, 6 Dec 2024 16:08:43 +0100 Subject: [PATCH 2/5] Add test for bold font replacement --- .../ping_fang_with_bold_in_style/expected.png | Bin 0 -> 18652 bytes test/text/local_glyph_rasterizer.test.cpp | 69 ++++++------------ 2 files changed, 21 insertions(+), 48 deletions(-) create mode 100644 test/fixtures/local_glyphs/ping_fang_with_bold_in_style/expected.png diff --git a/test/fixtures/local_glyphs/ping_fang_with_bold_in_style/expected.png b/test/fixtures/local_glyphs/ping_fang_with_bold_in_style/expected.png new file mode 100644 index 0000000000000000000000000000000000000000..88ad2d75af0e14ea979122d99af04c27f14c9465 GIT binary patch literal 18652 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 S?&yWV$8ST>`s?0Ny#E1}C^?A$ literal 0 HcmV?d00001 diff --git a/test/text/local_glyph_rasterizer.test.cpp b/test/text/local_glyph_rasterizer.test.cpp index 8e3235791c5..1922aacd97c 100644 --- a/test/text/local_glyph_rasterizer.test.cpp +++ b/test/text/local_glyph_rasterizer.test.cpp @@ -10,6 +10,8 @@ #include #include +#include + /* LoadLocalCJKGlyph in glyph_manager.test.cpp exercises the platform-independent part of LocalGlyphRasterizer. This test actually @@ -17,13 +19,8 @@ on. Different platforms have different default fonts, so adding a new platform requires new "expected" fixtures. - At the time of writing, we don't run `mbgl-test` on iOS or Android, so the - only supported test platform is macOS. Supporting Android would require - adding a new test case (probably using the "Droid" font family). iOS should - theoretically work -- the "PingFang" font family used below is expected to be - available on all iOS devices, and we use a relatively high image diff - tolerance (0.05) to account for small changes between the many possible - variants of the PingFang family. + At the time of writing, we don't run this test on Android, that would require + adding a new test case (probably using the "Droid" font family). */ using namespace mbgl; @@ -33,7 +30,14 @@ namespace { class LocalGlyphRasterizerTest { public: LocalGlyphRasterizerTest(const std::optional fontFamily) - : frontend(1, gfx::HeadlessBackend::SwapBehaviour::NoFlush, gfx::ContextMode::Unique, fontFamily) {} + : frontend(1, gfx::HeadlessBackend::SwapBehaviour::NoFlush, gfx::ContextMode::Unique, fontFamily) { + this->fileSource->glyphsResponse = [&](const Resource& resource) { + EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); + Response response; + response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); + return response; + }; + } util::RunLoop loop; std::shared_ptr fileSource = std::make_shared(); @@ -59,12 +63,6 @@ class LocalGlyphRasterizerTest { TEST(LocalGlyphRasterizer, PingFang) { LocalGlyphRasterizerTest test(std::string("PingFang TC")); - test.fileSource->glyphsResponse = [&](const Resource& resource) { - EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); - Response response; - response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); - return response; - }; test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); #if defined(__APPLE__) && !defined(__QT__) test.checkRendering("ping_fang", 0.0161); @@ -73,16 +71,19 @@ TEST(LocalGlyphRasterizer, PingFang) { #endif // defined(__APPLE__) } +TEST(LocalGlyphRasterizer, PingFangWithBoldInStyle) { + LocalGlyphRasterizerTest test(std::string("PingFang TC")); + std::stringstream ss; + ss << std::regex_replace( + util::read_file("test/fixtures/local_glyphs/mixed.json"), std::regex("NotoCJK"), "NotoCJK Bold"); + test.map.getStyle().loadJSON(ss.str()); + test.checkRendering("ping_fang_with_bold_in_style"); +} + #if !defined(__QT__) TEST(LocalGlyphRasterizer, PingFangSemibold) { LocalGlyphRasterizerTest test(std::string("PingFang TC Semibold")); - test.fileSource->glyphsResponse = [&](const Resource& resource) { - EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); - Response response; - response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); - return response; - }; test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); test.checkRendering("ping_fang_semibold", 0.0161); } @@ -94,13 +95,6 @@ TEST(LocalGlyphRasterizer, PingFangSemibold) { TEST(LocalGlyphRasterizer, NotoSansCJK) { LocalGlyphRasterizerTest test(std::string("Noto Sans CJK KR Regular")); - test.fileSource->glyphsResponse = [&](const Resource& resource) { - EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); - Response response; - response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); - return response; - }; - test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); test.checkRendering("noto_sans_cjk_kr_regular_qt"); } @@ -110,13 +104,6 @@ TEST(LocalGlyphRasterizer, NoLocal) { // Expectation: without any local fonts set, and without any CJK glyphs // provided, the output should just contain basic latin characters. LocalGlyphRasterizerTest test({}); - - test.fileSource->glyphsResponse = [&](const Resource& resource) { - EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); - Response response; - response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); - return response; - }; test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); test.checkRendering("no_local", 0.001, 0.1); } @@ -126,13 +113,6 @@ TEST(LocalGlyphRasterizer, NoLocalWithContentInsets) { // center. Rendered text should be on the same offset and keep the same size // as with no offset. LocalGlyphRasterizerTest test({}); - - test.fileSource->glyphsResponse = [&](const Resource& resource) { - EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); - Response response; - response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); - return response; - }; auto viewSize = test.frontend.getSize(); test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); @@ -149,13 +129,6 @@ TEST(LocalGlyphRasterizer, NoLocalWithContentInsetsAndPitch) { // center. Rendered text should be on the same offset and keep the same size // as with no offset. LocalGlyphRasterizerTest test({}); - - test.fileSource->glyphsResponse = [&](const Resource& resource) { - EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); - Response response; - response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); - return response; - }; auto viewSize = test.frontend.getSize(); test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); From bd22a852cf33a670edbac869a83bd62e9657165d Mon Sep 17 00:00:00 2001 From: Yingfang Date: Tue, 10 Dec 2024 14:04:23 +0800 Subject: [PATCH 3/5] fix comments --- platform/darwin/src/local_glyph_rasterizer.mm | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/platform/darwin/src/local_glyph_rasterizer.mm b/platform/darwin/src/local_glyph_rasterizer.mm index 39fd6d8c741..005989f57da 100644 --- a/platform/darwin/src/local_glyph_rasterizer.mm +++ b/platform/darwin/src/local_glyph_rasterizer.mm @@ -3,6 +3,8 @@ #include #include +#include + #include #import @@ -200,20 +202,17 @@ PremultipliedImage drawGlyphBitmap(GlyphID glyphID, CTFontRef font, GlyphMetrics throw std::runtime_error("Unable to create string from codepoint"); } - // Can't use CTFontRefHandle - // because the boldFont will be released after it is out of the isBold condition - CTFontRef boldFont = NULL; - if (isBold) - { - // Create a bold variant of the font - boldFont = CTFontCreateCopyWithSymbolicTraits(font, 0.0, NULL, kCTFontBoldTrait, kCTFontBoldTrait); - if (!boldFont) { - throw std::runtime_error("Unable to create bold font"); - } + // Create a bold variant of the font + CTFontRefHandle boldFont(CTFontCreateCopyWithSymbolicTraits(font, 0.0, NULL, kCTFontBoldTrait, kCTFontBoldTrait)); + if (!boldFont) { + CFStringRefHandle familyNameHandle(CTFontCopyFamilyName(font)); + [MLNNativeNetworkManager.sharedManager errorLog:@"Unable to create bold font for %@", *familyNameHandle]; } + + CTFontRef drawFont = isBold && boldFont ? *boldFont : font; CFStringRef keys[] = { kCTFontAttributeName }; - CFTypeRef values[] = { boldFont ? boldFont : font }; + CFTypeRef values[] = { drawFont }; CFDictionaryRefHandle attributes( CFDictionaryCreate(kCFAllocatorDefault, (const void**)&keys, @@ -278,12 +277,7 @@ CGContextHandle context(CGBitmapContextCreate( CGContextSetTextPosition(*context, 0.0, descent); CTLineDraw(*line, *context); - - // Release the bold font if it was created - if (boldFont) { - CFRelease(boldFont); - } - + return rgbaBitmap; } From cc4c4b1af3fbd5dfa974b1442319c5f887a2966d Mon Sep 17 00:00:00 2001 From: Yingfang Date: Fri, 13 Dec 2024 20:47:42 +0800 Subject: [PATCH 4/5] update expected file and refactor code --- platform/darwin/src/local_glyph_rasterizer.mm | 8 ++++---- .../ping_fang_with_bold_in_style/expected.png | Bin 18652 -> 17912 bytes 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/darwin/src/local_glyph_rasterizer.mm b/platform/darwin/src/local_glyph_rasterizer.mm index 005989f57da..17afef992e1 100644 --- a/platform/darwin/src/local_glyph_rasterizer.mm +++ b/platform/darwin/src/local_glyph_rasterizer.mm @@ -301,11 +301,11 @@ CGContextHandle context(CGBitmapContextCreate( manufacturedGlyph.id = glyphID; BOOL isBold = NO; - for (auto& fontName : fontStack) { - std::string lowercaseFont = platform::lowercase(fontName); - if (lowercaseFont.find("bold") != std::string::npos) { + // Only check the first font name to detect if the user prefers using bold + if (!fontStack.empty()) { + std::string lowercaseFont = platform::lowercase(fontStack.front()); + if (lowercaseFont.find("bold") != std::string::npos && lowercaseFont.find("semibold") == std::string::npos) { isBold = YES; - break; } } diff --git a/test/fixtures/local_glyphs/ping_fang_with_bold_in_style/expected.png b/test/fixtures/local_glyphs/ping_fang_with_bold_in_style/expected.png index 88ad2d75af0e14ea979122d99af04c27f14c9465..3de939b478752519d15009b0e599214f22765010 100644 GIT binary patch literal 17912 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 M)78&qol`;+05dZGSO5S3 literal 18652 zcmX6^WmuHo(_WS(mRvwmVyP7Y38f^L4nct*olApsNyE}09n!6IgCN}{9a56g4bsiK z{@+jgTzj3EnKLuzoH_R$uKZpWABPGD007|2%SovM0BERBGypax>POG1$Q%HW`zkLb zuI8R`xCBnLQFj$}P@WKAD`FxhQNf-{5GOKKB|_tcLb0VlQ6#KkczY(1@PN-!&oHDw zc%1_N0Yzcx0>M(^An_np?yhHX;bN*#_ZCHj$7;O^t8I0 zz_yT=pO*lediYAWX8Y~*-pb?Q%5TxA>h>=^Yw|BTNG=p|YuwNJJ!oG1o^7l5{2O7Y_t5WmFS}6qhHue*J!+c9ZE@n# zN|84nKy{t{bd$YD_w<*p)a$6R@bEv%myZuCPpwU-gKVYgc1^{%2Nq(wA}9WYWm&hs z3NVWB9l5pNsekZZBPn&A)&J2n=5zF)$bk`IY5lV2z66NSV?eS*>|si*-1jsg z`@2sGV<)Qp(%x3Oz1l6WhAl*E1=l0re7-QBY~SLo zEEYYDi%~<_;A#GHS4kuuaN7Z|`8 zT)r7~O9DI18HK7JyY~x~OuZK>Z@|R<(=Ybu=z6u}rYZJxGqxbQ=|LY*Jtlgmrfb(| zb`fECpLg4VC91qg9dxp%+3sn+nCi#?Mi4;y+pb!V>wKsfJEh6>)kJp02}>R??Vsvz zPeR4?qT3($+bbR)kDuCZSFyyjV2Y3q-@8N2!{*~Q+w9YpYm{GT$Q=?st`e4He)?T} zJDJ?3mNg$LdY=0cB}!%e(x-*Ji5Op(5a2ePxP!W?!|$H(W(Cm|mL@%f548aLwiFgV@C z8?#(zvyY>21}%?A!)+pR>VsJ8hCQ~)QR~(6G-_bY z^0wQ(X*R=~K_?ORKq-4Bv|)6dMy(rF47QMzn*#pUVjb6M^$1LdVeWplP--W+i*3Kh z?dgieV^vGsUi)2MgZX?>SBP7OutoV9WBW4W!9!_tEP{Fm= zL-K+Bn+&1cxh!gQuA8_HRnXM+0xIG@XZXD(IDKApkCOPVl)QCEdRpeWty(-DcfQT4JEl%nOH)1?OLd6ewWnPRWo<$x3r7^b*Gap&i!<*T+I*v7B79(Q6M zixkgMo>uNTq`Rz2oTUXW%y1f1(*;O)^wYTM(X)}I>fk3u+O(HewlxXf?tG1~HmRv> zIUST9%Rw8kzrNoVGkn%`VQy#%-I{dGLgqRJ+U5_~Guj-H-b(5&En3Ig^<3tf%{J zatYm%w2^OdATH2#wt`}L$vYy|^!x{zC}AK%B3%F*@e&SHet1IVBmL@+4IDUu^(ceJ zKTD**Ln&bVGC7raILuE82nEr4Y{b3FUb=5Ms2NhAAOQ!O=KI|i`mxR+H|XTygK0PS z;hnJ{E+*^`3c=yl@4$*a1%FrWM^?(*%ijZJsU4*vEcnF~AI*l6)W_WW-VA;wtUb`pjy-6Kq;b$C{R3gmG8C-jGVNGtsT ztEVF>OZ>?26G`nai3v-+JAIfsFr+|Dh8-o@J61>oyLQex%OEB!*u>FJwQ$%I?m{)&(dM)i6wv`u7POKbgDgy8oWa(#Uj~l+Smr7R5Xz z{dUc;ME9^GEB!zo|7GsmgQl^O98e3?^9{dGPzsx8I)!W?b^GaEMBQXWO#0mLHZDg) z&TSumo65kSaY@2gmE5)Zk_&MJZSA9NL1Nnle)QIWxAK_r&CnA6Uj@8gjxV8L1W_!n zrhWcMOw#+(snPGqx14&g;ZVR{!E1bER&_6#u39BZBOT$P;Tew! z+i?(nSHAe--$KD-9$pCl0h{INx?bmjSYH-{;561P1v*MKBRs2>k9(C{Ovpe&(T3jI zJ0Cgqf_(4uuXOr<)8t2~Vz0m2riQ`O?jum?FP5uwI>ovmx3@mKx2!IkIKJlhetRgj z7UopV-O=-v>ptTz=L~?Gizz9cNsj2g-r0!eI9xj*xG{Rq)%T{jL+e>bE??na%#wu-RJhUk} zsHmMb+9y8Vdeqcx=#A@ZVR`~!GJz`ul%<^ zD%@%7pPE&G6S3f;SUC0V#LurU)TE!@{(0$fZHwdYM8dK)%0KA;P!!~{|>NUP)+4!LSu)(>R?|g{T}w;vF*(% zECzj^(ZOV=TNqoO3W2g*tt1(q5``s>QWDJxpudF7l(k$=BupVL@(mR~eu+{NWx97L zw`6l7D?9H|vwOxibZOZ1;P4|!fpkk1b;e-m3^h-a>52hY>eq>X#@qNqvVvzy8kB(f z-){wbV=Oc+vx`w&U@T*YkGS!$tR#9$U>Qr(g7IINb@{hdBeY-H4{(h^x*aB4G~e|fnZykB+FF0 zDl+wc(7(KExjQY_BJ#O{mrtQrsP_)Q+m|Ys*o-ui;ngK)RXL@&G9UB`@!O5lfEBfW zqOt72yq^_nDFxT%$pBc6LE>!3OkOi8cjZ|i`BI@TG%r)7VCe+^PSwssHw#+-d1q1- z1)el?s=nS0R=A*x71>?11c2b%%|Bu3&uVIp>D*+bdh5Q=mm-o-`v?$Q<>h-L@QI48 zOs+(%7!3kr=cmQ%_r^{b5F})CD*N%=_*QpU3A!zDU0Xu@q$prp2O)h*mlJq@ZQz4# zvn9VFsW<=^#bBtCe)}f|9 zapD0opujI{%j~N3rr=g0+?R7OXu>B|8uu`yhH?RK-4e*;R(I2F#pg-_0Gk!PJNR$y z1Sb>HCBQ$GNJt+OaEZ*&l4fVx{52r^0t&r$RN4Vb_=P2g1W*%y6({ZpL%4os$n}i; z{W1S}42L*Ot7uWGLHUc=Ergx+&E+ocAx@hVNLc&2zIz2~^+>N!P6kpI=M2ltT1OC5{ z?(efik>C0sk9<_L_pJ6hD!$>9^I6GRZ#&!T+|9UOilxQ%EPdU90fN*nmdly>sK`f~F_ zm5vrnkBrP;39hBw1J_Y7c0surciA@;s$oCW#%;f_DiNmiUR2_QmPCo+eI=NiAPoDL zw8BU4%HbZzi|N`)658IU)VmAiuMFAdmM1q%rYNRz{t+7s)NTK{Q(=H2MsHE7pAd1>{Zh41!Em|2~~90^&P?-Zhh)Q z<#ld&c$L026Bf5e@M;65hL<){(IF0~fi??IamYXzo&2C#Bn~A_o|AQW!yRsSVWRga zMq<#ASSs!=1;S3)f|542VF4W8)!e&zqZC8m3)J$~zs!`PX3Oxsf>tiA7WTw68x4fN z$kJjbH2XnN5gr)4cJ~D=biYE+F567;0+Pcj76(}wA$Afo#r%xZW6l=-7j>|YTs<4? z+$LbL$7eQp-}dvxe)Jr#-N1e_awA8KtCdEsbF3@*^yz{9!2EUFvCr}II}drjNepao z180}7T*uX2yXqguP=@Acl!8Dsxk}!gFW9>JyMV`hd zA*RhL4VUHAo{;o3zXr~=d*Y;w^ntKh2$6Mgb1Vg2JfIIxv@+@~Z&NH?ju(Wv?XVSn zdTNTUfhA1g`H{MYc79n$!kod-9;fxBTbA$bu5{!#v;oX>D&klYc&S_@p*(;DdFv;k zabRjvm#)UGEOt^mjRAp`H^oJ>QCcoiy1~R45-|pz$nVJcm@#YMrW{USHC9+3%BPb$ zK=vW6mY`vW!{+{||2~M+L68j8UFmvW9ym&*zSIyOWpaALt|v3}&+$8Q?CGke#_>x3 zHAVjG*&iLw@xp*O@>O-p<|B<8FD*SW8iYP|{*sq^b|d-FQlj~Nz_$`9^R{8pq_`6% z5risOCHyId2}wrZt1cpZktqsAkGUCoMrVxqLlyDY!@Qkz9_OW4hiRN}kJ=20pBmSMD`(Pqch{Wrn8?tw*NAAydWbK! zUUrWQ>Wtf!bN^rS&CR4g*c8M?GTHMCL;0FGCsf~as3hMc zQk1rD6wV30nh-^)h3p{*Rc$8el5J+f`!Hf33M7;rqcKy<07^nKXc%(X+X>nC8=vcS z))@e{t>-kWzXt?21|5W$X!Knsr03@?KF5N_focmshxj|y3HFF`q_lQRxpH7MsxEN> z3SEvjyQq#M?_-}^OP2ea(^kBD>0r0Zt1kz%1P>aPUlWiR2)s`iO*z-YIBZnRP?_x_ zp~?sDw+V6JBRh&?=-m2w_wLyqIX4A{yb7`80k7beihf=s-Jrs2YoC15q%Tv}C0OB~ zT+k9M6U(cD{xm=pFFfa8&BEV{s)p4YMFh8EOHm)7p{zg%kjjzLUf|Y|$`fHi`wl2I zQ3JEO8{wzy5HMF6Y)h8XAn>6!uTb3K z!@SZ&>kxV`b{@wIeFAIPov6ztfRa@)_;Q$EPi@owyT}1B$q3JFB#feaMiLc5?rNt zz_RN)F6hlk1ev!&?`u*aK6D*XAUTAh#+D11KuV^3(994#?-xQ{rz1$=JpU0{UKe4S+5$ELwMjqgl#z6J0Gp@%~@!@4GBX zfRrG1r^bpNeox`aixMW11X*JEyYcvly%ihW(HBWH12%M_aEqEg18+UF;(jV*)$5c4 z+`m7iNy=_3c2U(tc3?p(L<-FkfD>(S-9=t8F2o}}5y{lsaTy01CuZv7(R@OF%k=zV z@UbZ%t@kLbl>Q}&@UXLn%m$snuWjpjk+Pf0EOD#KN#k40eev%9vSo)iCVOO96#Om# zs~@pLVZTwkz%vOCjwy-_Ko5x6(2yl)<@!?5B|%?I!siJ)P-CmS{&$JXUfsw2!8eM{ zuR#d2!XszH`-3x|7#N+Xq4jam8KINI`|wYwJ4b%Q+GjQm(}Qq4D1aBZ2wX$>{1{b#ZftC-#iue$1G5MV|s{wd8Y@*_vi9U~QV{m{knSarXHxthxeW*)? z@QEAKzy0MU`cw8iyW#SqPlsAT1<5qeIFELsNi-haiR$$3FJ4Qm(4P8^0Q7DbZGmnH7l@)Y&g=ij;pq`v&p5-R< z)6>q^7!F?iE?+6JZ*XtZa0s+^^J*2Evd6&e^k(prl|0}-5Mipk9S{d?kCyuGe3yK{ zX1ja;D?f`C@hxr@wCq$Oc8^fv+5}%}h~xMR_QoCl_gRVqD^rAcd1K{Dp`0j2rf>Q`W%XhpGzsMVKCVK zGfFDx57X*gQG(@*cQNW6r>o6gKHMaU`JDlA4MEsaLM}HKB8~lqe(oBtc|}a*)fZXQ ziw1F|bGpjvQws^BfLV^j9f|()Hm4@HJ5zM{JW9}1FW50xc?%DHoX3Dq&ghWXi8ic2 z)pW%uUj_maq95$-xH1!a3KsV#!w;EZR2$SMPBW|1#+Ff0c=aJry7-kYYQR70m7eMz zJ1?@mom?;HEs~{Z5;R7Tr0O*UVm@;ef+U8{M5(?iTBdmli`)%1gPqb^Hbf8-K0de- z9>JJ&ziFC0J3yz$W2OdfW}o%1${}Mye*;|fLCC3H~bfS`M zoat}(THyzAYN{WYnf3lM-W~e9;9SJ{fqH8Ag2#`p z-DvsgbMYYhMJz9-(b1cc>b5({Z~w7uG*SrPOI>+#lPyYsI}i--1+lt}&ae3GPTxL? zDk@8`)bMC3n$v6D5Yun)y{PuZccDA3V;R78tW*!tpVYMdvC`#km)drp1&K>!mb#s}h*#Nkblnmr^>Sp@CUB?TdOSVNI8(}HH#?<1bu{hkp1>(J}#^1MdX4I0GwC9dxG8*fhCjmKWS5v zEGAbR?^{f(o4w3qm}RJ8`pOW$xrpn@hjZmYSgrXwg&GGpU&$POi%69#)P}*NjbY7* zKQr?`&<5SDvUw(n)$QKv){G+GPboh)>L$LC@Vnzj3npfLHfg3{LTFMK;3UMcma~p1 zoqFi^JNDCP!rn4S<7nvD0gQkgy7gs{F5@Z)5DwqF6>%eq05~T|_v367p6Y@l^aC6t z@3myv7gNr8o~NdNE~}q2j;N7Sz4Ll#b+JF|p0U+%*CBj2u7wam@2X2k9HS?5E+yal zg#Qeqih<}hC5J;o=`EW-G}c-o7EE6`ODG%J*afzSUY`g(U3oW; z12e$()nAt=#^O$Te$1NqzuSInCNDFKKvcF8wTyj}$zsR$fkH}>9FATN;acfpN8(<2 zRx><~8^L{p)ziTwZSCT_#+j(VAm0V;Pa9}(lZS9UOKX6Tp=+4Hi0ZEs))v`=eNTiU z6)aLNY+fJMHpsHGK8pU8lS0sM@m>uo8B?Ep5NLQJnei zMRA1u2pU=jboSc+|*B7$bjj z&|{ztIDQJmW7k!``j6d;_;!ZdFFl-#c7Usw?HxwNkW`d>vvO_}9i<4Mj71Mmqp#`) zM1RlVbO9s-ik4=toF@G!bElh{w!RPy%*Q5)ENSbf^-3%#H~tIzns|6C(R;pq%H!jZ zFl{`rbipsz<#UV?!Ga5)VY<@Idv8<3`h;E$c~bN}x?-W~V-ExD05v|o2+3De6n(!D zmwpf9l|xLpsHUI`30e&gWK4ujmUO=A$O!}8HC{IbghLwW?rAqBtTnX>$HV24TERwRB;|-W*7;28r$TO&NA=(1 zSWVrWWAH0;GENN^r!3qfbyFwRt2nv#@S&Qpo#?Td#-A%xS4Xdsb+WK0Y1H}iF^B+U zk<;x*k~$;nKs;5vEz>3Tghgbn=MMP`wa!E{nOmWoQB}Gny}!1;63O37VY zz}f3(vW>~hJb{?Cv4`DDWB-cr!a|J{_X-;6*^N|3&Ej)xQRIJqT@kHTPTHAP{KN>0 zQjBv8>n`ibH~m7?NR%}Fn>D6~-Q_5JI?LLc_|1wd->FdJowL94zG!XJVno5h=kc36 zcAYD=I~R?B>LbH%G;7WBF%B~G3bvL&=rxzMFoN7n`GiqFOiiYeq+C%UbjSav9Y*qf zH&yJyF!^h2(uM|yx4Vj7WfreP6+SAT-r%d*NmiCgnir(^67OOVl1{MacM6cB^7US5 zRsXrE(!8cJ#s%w z!*YIOm62I4#0FB&xVWywUq>DZbOl``snaH9+!*9S0uzs={UB|xS@4hYmt*5GI*1Vk zGn!6Mr{s6jktB%LF&`IBEyI8Bf|TQbsmr`wf$$@}@7E%1Kw-lRkgL|n;qg~cMJ zW{|2$^ycT225$DHu>P}&#-_e+)|#38$?4rXT%XE!;!L*<-`K9 zjmy|U*%OuR)cid+M6HU?tdiQ&^F~=IH=~6Tkm@~ka-eF4Mlz;h>TO1aAwJ9f;sRGl zyf9k3hQ(_e)FZ_(Kxbf8SZNoE)rS8}A zvBa8z>Tu^+rQqR$)&Tr!ndo4DmNjA@^nigb{8Ec3G`a-k(h8`CQz`M)=U$}VU4C>8 zq-ABL_K~5VkvJ|^ga&ymCUO`@-~W-WKKW=lIRyf z#9su)rL6hu(^vGDFA8|kGvt305d1=~*Zdq`t==0ne%l@L)xo<3x30XOExLFyeF zvQo4G{;aMuI5PHJ%GwOHIkDfaQUREuJ3tX*oh9^y--r!9m1KO5QqqJ>uVB!1^djJC zrqcB;cbHt0q(v3Ss~oc6MVR@s}Me zSJ&@Z0XAlQ174}xazWZMnpLL=i)zc%kH(vieTWxw)u5v0uHYbAD$Jzq{@d0z*L&jx zD;+kH%;qmEqix8dqCQv_IPAJ?50lflyxT|3vIoP#9?v{z$RZn;2c3=L6hubFHfnt# z9;Mt!tk+U+r01Y{z3ZA%l+_%*926XaF?ejDJ*lCnH&cAK`@3s4hD)IOxlt8uBwYml z>+kNA>*r{GFCzKNc{$2?L4Pb>*C{^w9_ETXgQY5y7-sFL^MA$TV^jGr9N#q~ZK!Nr z!ae2DUekb3%Qs+}^Or3lfqxZWff=cFK)x{s`4P{JHk^k7WM$?Yg(+~+v^z?%s1)}M zO{z^sOu0~+Y%e|G);9s@!Kl2l$(w{lRBl_P25HyWRth5P75u*AApQ!QK7)#UAZj;8 zQ3;VP2_mIIyUJ4i;KlvP6l+q=TZZNzoP|EbY8kEZA{y@OD$rX-#W+sJfH4o>@M1tG zp$b0-UIhdjxe7m=PeovN-^V~;B-(XJoygwu+hP51x{HEzIf(`v>ID~k+@xqUi}ow2}$|E?c{WbEvy?(6I7F^}}sKd+l& zRBimTdIya!YxA^Hq=XCF?$|eIfDKpl23N~-r~FD+j=x>=XTS)K6P0S`DJJsgbxmIG zrx>1J;GVG>FVT4=^c1U$eyz1rey0zSujWb72J~bB+J&529dwTUe7D%mP_kJcs{8edu|RMr zgl#7+HdsCy$_{b?36h=}IQ>4|9MU`pWB*w7i)$Lx@w72@rLamQom2KPqSu?B8R%zwiyJve7&86egHZN{C5I0k}*l?RJdPg=bkBizygwEvU<<3rMj=r==q z513T~o5?r*YJD@<3~B5-^TAB1jzrr9mbyw0He4xcuG0L7jv>mE)vqGSfj@`LVjt?~ z+QK4&!xu|sj5(mgM%W!*p^n@#Xk*y`D`_%?q;uw35ZXzzmo_yI9cY!3{*zggqF<01 zH@6Hswq5~D3r9+IOzm4w1GjG^GY7_xUvm-+waQ7N7oc%mSjD(ndx^kc1D3gjtV}YG zHs0tWA;j|f2?k6cC_aCe10JWh#KQdQ?$Ej$C?}~!XbbQ9#TBkp;gxc^1RG_-YW-91%%FRBL7 zyWksHY!Q{@R*od5VKu;p7~?C~b?{?B4VwB%Y&&f=68TI@vu}3DDOtl9jFzgw=^AVEb}XmF@c_%ok5`@ zxwm*|DbTY`yh!4Kv}FksxG+r6C??-*QwCJV70wqV^o>0R{rbe)Ia~Z7f^2_vzQH^% zYx{kB%CRqfY`uPqqmeln5XSRNANI9#)P{+5@Mqu7y;R^ZtEgewOb2&WOSWMVP(>z1 ziYS3Dl}mF!)1Z-FgK_?|qUw>H%^@#`g9_#nCqfzM@C4JJ4~-1Aj4P2J*1^qHYM80T z6A5`eR%jmr6~VO&TqM+xI0%t!F`JN+c_UiDD{n!ZVg*DjPv2oduEXSE`J|G6L#xuX z+JCb0%vIvP?$uN4T!8}P&>Rs>0cdk<`7>~{wp00s^4NGu{uRef(kcbKQ*niCqFyLy z_4mTgq3mW1k52yPu%`~b8$Ni-U2)a&%}NW|mBdaGn_NRFIlDiPp^3PNoF?}aXdF~P z{&tm$i-@$I>jiU-^5>U}txZs`N{UMGhhV<2l)sozdM8om<-41r3(zworf-b;UxbWL zq7}4W8)3;?$NqnN+6F^FVT-L6#d9bD;Tpzep01VPAcx0c`_MAYaKD%w**Q?^; zwMsMcJrSG)6XR?$=$SS)#lf(YF9Tg%GvdU<&@{3W>f53|fT&YVJr81HODzggAKH6H zFKvFv0uS1_8g=sxga8harqpg#PEBV->A; zPrr>@0Rh^6BMuBIa&w`U1KTl+4u?5qzXDTcF>}Q~u1a%*|0*ZK#R-%;a!4~*zv}D; zWyoNF_*OP(g8+&}j$f`P<*{8`2d&VDoyU;*LEiZb3??%PI4Z%0N0o|78oHIv%oMLL zwoAPa7z956S`mmn`GIpab43ADJDE^}z?$X0VuI3&60Vm`FdvuUsFuHTM?yLxy80$7 z!M*kF6@mHOhLWQ<*d46DD@T5_KyCVgCScz5SWwyTAmJ;8XYkXQk8%Oo*Z_uDZq`8( z`em3F&?SyLCAp!a;E3@l_HHa^JJxr(}0<$cqyZ8Kf&%|iG7#7j$D-GKg`>gtDf zRB{TPJRm|!1mo?cAW!wz>M(J3C+N9sI2oUsc0ribBXVUV*{4ByIJw27>tcZ%SvO^` zPD`3{QC-ZAD<3T-LfPL)qQ9hR2h_v|Lu|fEWqe{JdY9NMqJ)Qf9w+Mh$SQ2sn+!1R z-4=DgaG{QG`j}&Fr{HZ2ywetIcg#;plRBOCGU5P2@G0w+Ew$tt^CMEOKOSnoKZo=% zA6U8;ibJ)e*lfsYvKcthz$_` zTEis<8&re3)pvt^LD0|0jz0WcwJVvAmEd7dr)+E=jk`HulzS+X`eyNt4UW&0azKk3 zs#0sLb@5e6;w08p;jh-NAPchLbUvv^;1a`ft-8T4_le zU?YzYP`hO&fK*Qzt%bMnr|#Tk-M_^*qaP-s$Q;XnqOG3y0)Bsh?W$W5+5WxY}`I;SLt)2{#z>y_~Z&tO)q8kl&w)R`RKdMg*14f_7 z$?&1y`K;-sKE}S|B+hMZAasOE`HcylR*r2*OjrjI1^f3a$&5;thu`toMMeTr>Ld_~ zKa7T8V0FRs!D>3P#~I04%1{Oy#?VIMcWJTsJNA2|ChN#K-fD%^n)4}3PRt9Afs1Dw zDtVeRhMYi%x$eN_`a?(1@efq+bAIB9Cqz9-U46Kh#F2v&0QNgJN{{)LaQo1d@*DlW z1+mHNw^j^^#F-#%AhkH}vx&rNN41=)pU0LdC&_1m^kRy@e_s=Hl}c8Gb-#&bY{I+> zEQ&oY2>$iQYxva)Z%IZ-E;hV{>dnUh%bb}AHkLkB{c?v3@y(FmYW`ro(5pMI&;oo7 z$?9eCwszX)B=v3k-bGtIBWe2Yyt!dg8d(I~t|#qFHrrfwJ*$UTCyeyi#i^hXj)4gO z}Y`9~^z(7ya|aMgaO$l!+bRk6{VGqk(o6m|N+t9s^TeoECJ1&d=yXphfYwOz%o! zA$8iVyIA(^R^Z0VQmP+vMPqRCSJgmI4n;)52r7Q_y7}$88lOuNfA-85V+3USdo~uZ zb0h^mGudi2Akrfe+ZSIwJNMusYAj;cN&0prlf)Dt@o5WAokgzMvlrbGi&e_NM_!&? zxc##RpQh`Y>@;z|!za&hE>7ze4%^5>R;9;C4n+#UrK?lXbt{4Mm^XnHyF=2co3xRu z_m&6=4ppO85XPbhm@@zoB3k(P8{*hVLRs6s66`Vqe!HCB_$;VKX}68g9B~#^U*3Ub4cj^sUO=njGi~* zz%Y6OlF?et(L>*va{6=^tw>?72$iJ(hpav*$x3(QADfK1`PnbLqVe*ywJskjYcDTMGd5qcs%{M3IBSWS50MkL3H4fQ zG9Efp$wl37H$PQkSz%}#ACZ6%7$jL4oH+gtA{G_Ev!#`ol4yGDjx#t5J1}AX&t2C; zt#tya%4y{7UBL*2C(g8yYoBY;$N zSweBCzTBET9S!TO>HJb6CNpz&a~F*7m~6U}=WG|WqI~ce%ycB5bI6mlF~*PT`Te(e z80ru1z;|OzeWWFDO`Pj|RrL`Q&0S6d;{^hafwr@|b(|vlm^9~KTxLn(ElLDguN5fU zSRNu4=bie2mR%+C09A*4J_CTst%q z{GCi21X>71g9xMr+hCWC%<2I6PoI&o7uhJCHiHtDI1e_m${a8C+jkC=i4EQ(EgU^k zTw1rtq7nR*h-OdqQA#D#s_PoB*{hFdGgdUqJJuAZj^5-#cgq2!O zbOzv=5tpALjDMKPspfWx+i!akuxCRSidC|;EV=6DVaowT7GZUZDVU?=aI#YK*`gtffgSS1CKL5%kNlb<#E(ET-F??yYU>;|&O>klUj)FZHwF z_85SocN2W7FmmLzNzL_>z>rm3l10~W)EBzcYD{XJ04<{~k3R85w{}Sd0?;_y=UgIo z;LaEP-A8v(SduhBaV-V&i?`VT@*d}D-HxD*g)xlBw#KerSKAuuJ9PsFO{qT*>;SS* zYw^)C^>y7upX13<~KCWd`ui5B4Zp z#ttg@} z@gS=k4-H~dhBns7H=6q1iZ(VjRoCtNmTAbpq6Jj`(R4e193sk4XG0e%42Hd+lD)}a{GJov1o=FM6uLH!`mk+g@K4_S1ahxq!XT^o@q&EJ5Avje?!-S&y&x1siTg`JtIYEAlZLMf)Qqn zL2ygl(O1|aSznH&2_%V-`~;p{){88PbN88@((?HDIX7MjGZ;n=Z3J<>-L8NC{NOV4 z^r@8JmXTWFw;79+6;OmJ?w^&9+hyRx*X?hNhZzI0!l87c-%3Q7Iu1@(l|p=HZO3oC zj-xCCI?a1`E<|BzcN^l3d|0*7Ya+uBwEafGi9G>o<@Fk}U)+OUkx?>W&*pe&`J{!4 z&+c2wNK%uz8pzp?cO^tpG<&79S=}K1tkOt=Av{(g6W~n%47+Ny8l~j+@Ox;% z$KJCKdVQzwrf3ryC6kI&>C+J_bk8P@yr!7IR{`?-rg({j2VzR7*tLxYSksn;Y!Rhq zTm+g;>=*S9tRpUk)qA}Uxm=E!B&CfWT8;Zy zLtk)Lh4d=HHo4!G>19B+8H_mV3vPF9a`8^%1+g^b9a{Wi4b3Bg(t2VcPH3h^Z&jjR zl~X)K7tn=3xT>CiW!6X;)k8nt1YTzb#TZ!j`Ru1~5(0*5X@%7STaSdA+U%{UvA=s>#^TBT1se`^q8E=2}FGPo%bSRNWm115rYZIwI{@UBR1P9P+x?X zpcbqcm5LoPJWa3bs_798Tx*jeC@c&+Ay3FxmU5zev5+7ThP0&PE(K zPK2~hVJp+^R|dhyWAWasblO-+Xe50}5LCE+gBC8P_>sI}ymdCkkYi@#&EH+zclI|r0Sc?tog>e#R;4hE z84nP|1M^%&2@o$yqMB5vY%zq-qkw#&^faHS^IOC7QBWTO$)pVd{wGC6v45?t=BDP* zxw+pmp}9~@n!ivv&Q3A-_dRGAYRj6I^6G#8C(AbCDjV<8qh?YD3Rx09_1G}{`^L&% zuyuPb51FU5 zlA0TiN0$jHzW>HQvvr6|K_LfSDEJyuei6XKccoAw=MJ6aw5}7^hBG0fCGe3-dTFhP zBuf&+aI9S5_$S>;_g=P1;En)lV4%;Mt?$cAdokfV^0`E5YlrqJS{o`pu)HD}N;dx` zSDQfdm8Q9(>F8m;T9>)Wkr_Qo(jBsYJ)i5^eV>rY$8V6yd92H?kA~|3z1V(lkIR&W zAEAJ1j8!9b>dT|m^||%U<%ji$meyk)&HM||LfrxXB#}h~|FHUo&u5GD=%chqRMKw5 zEJN=>SlbnMDg-59H=$T6(H&&-gx;&@rEkWBYX$EPYKI&Ts{4~faK&yXVl_5%$+jPS3toCBC{=gIC-ye1nWkS*jNAJZjR)Zv$kY@JV2 zI2eVO?#n%^v>p1f=rmOG`+vMu0^yU6y!?yKeX8IrdYR_ZL%K(J~^ZMdv_^_u*KGd;6 z4jzb-XbNURQub%MEo(pgBa{BEz4cRQ$Lsjfc2O>U@)fPD{`bde=j^*hvN4{CfBp-Y z_aXMCCO7nUbVZRV6RDA*!W;C{{}Az$NJA7hkIW4^f%3{>0ZRbv>eGU)rXJehQ`3Hh zu3jJtRr(Ol7l!km7Fb>Pdnps>RfRsBDp$Rd*%VQdZ$7qgn#C>CESmhdXtG(P|0 z_~lEO4k{Y4a;ichEcn+#D>v^wlrW(ehVkS77@~QkO#cgxRTL@KpbiBtQV*r|-1$6v zgi;Sh2f}3~Ng|Kkp^XQaQ+IjaKJ8+f)>XFKO>2S&FdA;Q(shN0q;ydV8=YKy5IX$+ z`sM_=N1ca1Rt#QaInS=zp|H0hxtqzOVpw$E z4ln<{P#LbFf0 zgM@$)IMZ2EzU%MLxM846Im3uJ)Wd$ zLgx7wn!tZ7{W_o9aPU9pp&#yV(F9vsbLDsF+SaMR#PdXP?)5(5`L2;6uO6j=AKbf0N|IYPn9UN#{{i*GkT?O~u_`U_ zVCJapZ7G0}P0deO@Uz#{bNHydz{PXR zbU9C?6-vj}iV1~16{OqgO!|fUNp<`qbqikn`tO|!{F-ax|Jy!%d;IV6YT4^}ZJW-q zhiLju*5AlH@Bp3^K*I;c$n31g8M1>fp%^xJl0*>P4$ulJ=Y7UNkSOOt^Z&1etB+?o zkK@0M&2SzxpIrl1*$Gf&PvNhdB<&uQD9-M0`qjXwS$EH%^ zRYc0ODO4+=*tE@l_xY~$L)ws zlr5GHW~u70Z_PK;Sk?m!TiWy7*5ao=rd2TNZ%M{4`nf!nM~tzm3t0!+2anOBmbo@NIIaYOz5o_=KHveB!P1-XWkR zdJqs$hpRr~Dtt{A=jOrKl6laL4wIzDbbP&u_{4)_K~vS9x&L9*b_^M3&v5woUfskm z#`hT`*nWLfn7UdiH3ah)Z4-SGoA6Xl3u&>zOUK_Vkk{nRa$sUdIVt51$S1Z9)+=eF9)rHIqCfe-_DM9pLl2*ZmSz{aQIBZrAX9W@2q8g z2L@*U2sc||)Jp1C_RGV-wVKqkuJ)leQ0>aBDXOxoW%&m0g(``T0MYDa@})zvt}cU` zOgP-)GRbv{j|s>xuq}nf<=96gW5|ovMeyP&{?>u}k@UHbER0g-jkE~nSlYn7cw(M9 z1C-C=Vwpg0Kds3P@OXQ^UFK+4iotTOw60dxEtu3^@fFQDNsl>Qk5%3>3FU$)5*I|x z%?MUCsD*?o$4xeHgM>!RY~&wB=29^`F1h3$dZNpU5puCEd^2{#fO7joS=wqK_!qMG zwwep@?k}9ceL-Dx*cI;joF@8Zw)?pVo=H^>Y@$EN#cXx+Om#q|v#7*{dx$Wpy>_zI zM`QEn2TuFZ**{GwUWw{P+k*m)p}Z&NCD#1i9hGU||5T*Fkr6*%)ihJ6SH7yoCw4sK zBzw!j(XTC>jGikOimVYW1+x8U3TzjvYd3%5=+?+YG0f+OTP2GLe4BAd7huKBVkt+f zs}D70>%u$onMR60ip8sLg4ifbxNoZyr^EVCQN712SO-0Q=lr3{2Zl~hXuGh}3ug6x zh?Fm-IvD^x-)avEFnI?KaJXceQ=MPp6^RnKr-5W__+oKz+&IcOC^2&XXp#TU5bZyf zGGr>I?KpWpSl4z>Q2_*+R}bDLjlp^NRyEml?ev#b7tj1i@H_%<=@H67Xj3#7Fa~h7 z{5Yj?5^Q;W0%Qzruxqt2n`#F8y$H{rc>R@dd%K@mH(+cTBC5Mzo_Y4H>qD)&;!TaTOyJ)_ZJ?%og#Sfc z#K}DCYxO77hZYOAhDQi@K-&ilh>;UN;nJ@fZcRC#`Z}9G{Z^7`wA_-L{B^i6d}mTE zQwW~bd^VEPr8|;pr^*od*61Okp<%T&|O67|Tg?K(^4o0jzN{hEXr$J=QQ#*xZTn`yFkqN?%u#V@x z3u~i=_Nq}4uI78hhLKo+xmLW6$X*=sV>UCWAqW7|LHaC95SySv@kqJR3{6#1a3nnw zE^Um~(=2*3Z(x(~+W`)G{z57N&h+q=NIlhN>!zvfb%?@{UQGKGr*s1}!bwk0ZR4%q S?&yWV$8ST>`s?0Ny#E1}C^?A$ From 47feb2dbcad48581d5e44566a6e2f083d6994380 Mon Sep 17 00:00:00 2001 From: Yingfang Date: Mon, 16 Dec 2024 15:10:55 +0800 Subject: [PATCH 5/5] fix comments --- platform/darwin/src/local_glyph_rasterizer.mm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/darwin/src/local_glyph_rasterizer.mm b/platform/darwin/src/local_glyph_rasterizer.mm index 17afef992e1..eef0bc31d4c 100644 --- a/platform/darwin/src/local_glyph_rasterizer.mm +++ b/platform/darwin/src/local_glyph_rasterizer.mm @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -206,7 +207,9 @@ PremultipliedImage drawGlyphBitmap(GlyphID glyphID, CTFontRef font, GlyphMetrics CTFontRefHandle boldFont(CTFontCreateCopyWithSymbolicTraits(font, 0.0, NULL, kCTFontBoldTrait, kCTFontBoldTrait)); if (!boldFont) { CFStringRefHandle familyNameHandle(CTFontCopyFamilyName(font)); - [MLNNativeNetworkManager.sharedManager errorLog:@"Unable to create bold font for %@", *familyNameHandle]; + NSString* familyName = (__bridge NSString *)(*familyNameHandle); + std::string stdFamilyName(familyName.UTF8String); + Log::Error(Event::General, "Unable to create bold font for " + stdFamilyName); } CTFontRef drawFont = isBold && boldFont ? *boldFont : font;