From b222ad5dbc85956228b5dec5a2d4e009074c1f44 Mon Sep 17 00:00:00 2001 From: Heiko Klare Date: Fri, 14 Aug 2026 23:38:11 +0200 Subject: [PATCH 1/2] [Win32] Fix tab stop width in GDI+ text rendering The GDI+ based text rendering path in GC.drawText() derived the DRAW_TAB tab stop width from the width of a single space glyph, while the GDI based path and plain (non-advanced) GDI both use eight times the font's average character width, which is the convention Win32's own DrawText() and TabbedTextOut() follow. Those are two different metrics, not two ways of computing the same one: in proportional fonts a space is roughly half the average character width, so tab stops came out about half as wide whenever the GDI+ path was taken. In monospace fonts the two nearly coincide, which is why the discrepancy was easy to miss. The GDI+ path is changed to reuse the GDI text metric already computed by its caller, so that tab stops are sized consistently no matter which path renders the text. This restores the behaviour established for the GDI path in bug 289244 ("GDI+ drawText is not consistent with GDI"), which the GDI+ fallback path reintroduced in bug 305815 had missed. Add tests that pin down the tab stop width itself (eight average character widths), its consistency across both rendering paths, and two properties that must hold for either engine: consecutive tabs advance by whole tab stops, and text following a tab starts at the same tab stop regardless of what precedes the tab. They are measured from a leading tab, which expands to exactly one tab stop and so is not diluted by the slightly different glyph advances of the two engines, and cover both proportional and monospace fonts. Add Snippet395 as a manual/visual companion to the automated tests: it renders a series of text properties, one row per property, and offers a checkbox to switch between plain GDI and GDI+ (advanced) rendering at runtime, without restarting, to visually compare the resulting output. Assisted-by: Claude Opus 5 --- .../eclipse/swt/graphics/GCWin32Tests.java | 179 ++++++++++++++ .../win32/org/eclipse/swt/graphics/GC.java | 21 +- .../org.eclipse.swt.snippets/.classpath_cocoa | 2 +- .../org.eclipse.swt.snippets/.classpath_gtk | 2 +- examples/org.eclipse.swt.snippets/Snippets.md | 1 + .../previews/Snippet395.png | Bin 0 -> 38049 bytes .../org/eclipse/swt/snippets/Snippet395.java | 224 ++++++++++++++++++ 7 files changed, 417 insertions(+), 12 deletions(-) create mode 100644 examples/org.eclipse.swt.snippets/previews/Snippet395.png create mode 100644 examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet395.java diff --git a/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/graphics/GCWin32Tests.java b/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/graphics/GCWin32Tests.java index 47b20458042..d6af2d2c10b 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/graphics/GCWin32Tests.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/graphics/GCWin32Tests.java @@ -18,6 +18,7 @@ import java.util.*; import java.util.concurrent.*; +import java.util.function.*; import java.util.stream.*; import org.eclipse.swt.*; @@ -146,6 +147,184 @@ private static int renderTextAndCountNonWhitePixels(Image target, Font font, Str return count; } + /** + * U+FFFE is a Unicode non-character that no standard font has a glyph for. + * Appending it to a string makes an advanced GC lay that string out with + * GDI+ instead of letting GDI compute the glyph positions, which is the only + * way to exercise the GDI+ tab stop handling. + */ + private static final String UNSUPPORTED_GLYPH = String.valueOf((char) 0xFFFE); + + /** + * Fonts covering both ends of the space-width/average-character-width ratio: + * in proportional fonts a space is roughly half the average character width, + * while in monospace fonts the two nearly coincide. A tab stop derived from + * the space width therefore only misbehaves noticeably for the proportional + * ones, so both kinds have to be covered. + */ + private static Stream tabStopTestFonts() { + return Stream.of("Segoe UI", "Arial", "Times New Roman", "Courier New", "Consolas"); + } + + /** + * The extents of the GDI and the GDI+ path are each rounded up to whole + * pixels independently, so measurements derived from a difference of two + * extents may legitimately be off by one pixel. + */ + private static final int ROUNDING_TOLERANCE = 1; + + /** + * Verifies that a tab is expanded to eight times the font's average + * character width, which is the convention Win32's own {@code DrawText()} + * and {@code TabbedTextOut()} follow: {@code TabbedTextOut()} is documented + * to expand tabs to "eight times the average character width" by default, + * and {@code DRAWTEXTPARAMS.iTabLength} is documented to be measured "in + * units equal to the average character width". + *

+ * This pins down the constant the GDI+ path is expected to reproduce. + */ + @ParameterizedTest + @MethodSource("tabStopTestFonts") + public void tabStopWidthEqualsEightAverageCharacterWidths(String fontName) { + Display display = Display.getDefault(); + Image image = new Image(display, 400, 100); + Font font = new Font(display, fontName, 12, SWT.NORMAL); + GC gc = new GC(image); + try { + gc.setFont(font); + int averageCharacterWidth = gc.getFontMetrics().handle.tmAveCharWidth; + assertWithinRoundingTolerance(8 * averageCharacterWidth, measureTabStopWidth(gc), + "a tab must be expanded to eight average character widths for font " + fontName); + } finally { + gc.dispose(); + font.dispose(); + image.dispose(); + } + } + + /** + * Verifies that tab stops are expanded to the same width no matter whether + * text is rendered via plain GDI or via GDI+. + *

+ * Both paths must use eight times the font's average character width + * ({@code TEXTMETRIC.tmAveCharWidth}). The GDI+ path used to derive its tab + * stop width from the width of a single space glyph instead. That is a + * different metric, not merely a differently computed one: in proportional + * fonts a space is roughly half the average character width, so tab stops + * came out about half as wide whenever that path was taken. + */ + @ParameterizedTest + @MethodSource("tabStopTestFonts") + public void tabStopWidthIsConsistentBetweenGdiAndGdipRendering(String fontName) { + Display display = Display.getDefault(); + Image image = new Image(display, 400, 100); + Font font = new Font(display, fontName, 12, SWT.NORMAL); + try { + int gdiTabStopWidth = withGC(image, font, false, GCWin32Tests::measureTabStopWidth); + int gdipTabStopWidth = withGC(image, font, true, GCWin32Tests::measureTabStopWidth); + assertWithinRoundingTolerance(gdiTabStopWidth, gdipTabStopWidth, + "GDI+ rendering must expand a tab to the same width as GDI rendering for font " + fontName); + } finally { + font.dispose(); + image.dispose(); + } + } + + /** + * Verifies that consecutive tabs advance to consecutive tab stops instead of + * collapsing into a single one, i.e. that the tab stop width repeats. GDI + * derives the repetition from its own {@code (position / width + 1) * width} + * calculation, whereas GDI+ gets a single tab stop distance passed to + * {@code StringFormat::SetTabStops} and repeats it internally; this asserts + * that both arrive at the same layout. + */ + @ParameterizedTest + @MethodSource("tabStopTestFonts") + public void consecutiveTabsAdvanceByWholeTabStops(String fontName) { + Display display = Display.getDefault(); + Image image = new Image(display, 800, 100); + Font font = new Font(display, fontName, 12, SWT.NORMAL); + try { + for (boolean advanced : new boolean[] { false, true }) { + int twoTabStops = withGC(image, font, advanced, + gc -> measureTabAdvance(gc, "\t\t") ); + int oneTabStop = withGC(image, font, advanced, GCWin32Tests::measureTabStopWidth); + assertWithinRoundingTolerance(2 * oneTabStop, twoTabStops, + "two tabs must advance by two tab stops for font " + fontName + + " (advanced=" + advanced + ")"); + } + } finally { + font.dispose(); + image.dispose(); + } + } + + /** + * Verifies that a tab advances to the next tab stop rather than adding a + * fixed amount of space, so that text following a tab starts at the same + * column regardless of what precedes the tab within the same tab stop. + */ + @ParameterizedTest + @MethodSource("tabStopTestFonts") + public void textAfterTabStartsAtSameTabStopRegardlessOfPrecedingText(String fontName) { + Display display = Display.getDefault(); + Image image = new Image(display, 400, 100); + Font font = new Font(display, fontName, 12, SWT.NORMAL); + try { + for (boolean advanced : new boolean[] { false, true }) { + int withoutPrefix = withGC(image, font, advanced, gc -> measureExtent(gc, "\tB")); + int withPrefix = withGC(image, font, advanced, gc -> measureExtent(gc, "A\tB")); + assertWithinRoundingTolerance(withoutPrefix, withPrefix, + "text following a tab must start at the same tab stop no matter what precedes the tab, " + + "for font " + fontName + " (advanced=" + advanced + ")"); + } + } finally { + font.dispose(); + image.dispose(); + } + } + + /** + * Returns the width of a single tab stop, measured as the advance a leading + * tab adds. A leading tab always expands to exactly one tab stop, so unlike + * a tab in the middle of a string this measurement is not diluted by the + * slightly different glyph advances of the GDI and the GDI+ text layout + * engine. + */ + private static int measureTabStopWidth(GC gc) { + return measureTabAdvance(gc, "\t"); + } + + /** + * Returns the horizontal advance the given leading tabs add to the extent of + * the text that follows them. + */ + private static int measureTabAdvance(GC gc, String leadingTabs) { + return measureExtent(gc, leadingTabs + "B") - measureExtent(gc, "B"); + } + + private static int measureExtent(GC gc, String text) { + // measure in pixels to keep the comparison free of the point/pixel + // conversion the public API applies at non-100% zoom levels + return gc.textExtentInPixels(text + UNSUPPORTED_GLYPH, SWT.DRAW_TAB).x; + } + + private static void assertWithinRoundingTolerance(int expected, int actual, String message) { + assertTrue(Math.abs(actual - expected) <= ROUNDING_TOLERANCE, + message + " (expected " + expected + ", was " + actual + ")"); + } + + private static int withGC(Image target, Font font, boolean advanced, ToIntFunction measurement) { + GC gc = new GC(target); + try { + gc.setFont(font); + gc.setAdvanced(advanced); + return measurement.applyAsInt(gc); + } finally { + gc.dispose(); + } + } + /** * Regression test for the size calculation in scaling/cropping GC.drawImage() * operations with asymmetric source dimensions (smaller height than width) at diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java index 525cf88296d..cb4246c32d8 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java @@ -2886,7 +2886,7 @@ void drawText(long gdipGraphics, String string, int x, int y, int flags, Point s if (hFont != 0) OS.SelectObject(hdc, oldFont); Gdip.Graphics_ReleaseHDC(gdipGraphics, hdc); if (gdip) { - drawTextGDIP(gdipGraphics, string, x, y, flags, size == null, size); + drawTextGDIP(gdipGraphics, string, x, y, flags, size == null, size, lptm); return; } int i = 0, start = 0, end = 0, drawX = x, drawY = y, width = 0, mnemonicIndex = -1; @@ -3056,7 +3056,7 @@ private RectF drawText(long gdipGraphics, char[] buffer, int start, int length, return bounds; } -private void drawTextGDIP(long gdipGraphics, String string, int x, int y, int flags, boolean draw, Point size) { +private void drawTextGDIP(long gdipGraphics, String string, int x, int y, int flags, boolean draw, Point size, TEXTMETRIC lptm) { boolean needsBounds = !draw || (flags & SWT.DRAW_TRANSPARENT) == 0; char[] buffer; if ((flags & SWT.DRAW_DELIMITER) == 0) { @@ -3078,7 +3078,15 @@ private void drawTextGDIP(long gdipGraphics, String string, int x, int y, int fl int formatFlags = Gdip.StringFormat_GetFormatFlags(format) | Gdip.StringFormatFlagsMeasureTrailingSpaces; if ((data.style & SWT.MIRRORED) != 0) formatFlags |= Gdip.StringFormatFlagsDirectionRightToLeft; Gdip.StringFormat_SetFormatFlags(format, formatFlags); - float[] tabs = (flags & SWT.DRAW_TAB) != 0 ? new float[]{measureSpace(data.gdipFont, format) * 8} : new float[1]; + // Use the same tab stop width as the GDI-based text rendering path: 8 * the + // font's average character width, which is what Win32's own DrawText() and + // TabbedTextOut() use by default. This used to be 8 * the width of a single + // space glyph, which is a different metric rather than a differently + // computed one: in proportional fonts a space is roughly half the average + // character width, so tab stops came out about half as wide whenever this + // path was taken. (In monospace fonts the two nearly coincide, which is why + // the discrepancy was easy to miss.) + float[] tabs = (flags & SWT.DRAW_TAB) != 0 ? new float[]{lptm.tmAveCharWidth * 8} : new float[1]; Gdip.StringFormat_SetTabStops(format, 0, tabs.length, tabs); int hotkeyPrefix = (flags & SWT.DRAW_MNEMONIC) != 0 ? Gdip.HotkeyPrefixShow : Gdip.HotkeyPrefixNone; if ((flags & SWT.DRAW_MNEMONIC) != 0 && (data.uiState & OS.UISF_HIDEACCEL) != 0) hotkeyPrefix = Gdip.HotkeyPrefixHide; @@ -4658,13 +4666,6 @@ public boolean isDisposed() { return handle == 0; } -private float measureSpace(long font, long format) { - PointF pt = new PointF(); - RectF bounds = new RectF(); - Gdip.Graphics_MeasureString(data.gdipGraphics, new char[]{' '}, 1, font, pt, format, bounds); - return bounds.Width; -} - /** * Sets the receiver to always use the operating system's advanced graphics * subsystem for all graphics operations if the argument is true. diff --git a/examples/org.eclipse.swt.snippets/.classpath_cocoa b/examples/org.eclipse.swt.snippets/.classpath_cocoa index bcad73af751..6f6d5d56841 100644 --- a/examples/org.eclipse.swt.snippets/.classpath_cocoa +++ b/examples/org.eclipse.swt.snippets/.classpath_cocoa @@ -2,6 +2,6 @@ - + diff --git a/examples/org.eclipse.swt.snippets/.classpath_gtk b/examples/org.eclipse.swt.snippets/.classpath_gtk index bcad73af751..6f6d5d56841 100644 --- a/examples/org.eclipse.swt.snippets/.classpath_gtk +++ b/examples/org.eclipse.swt.snippets/.classpath_gtk @@ -2,6 +2,6 @@ - + diff --git a/examples/org.eclipse.swt.snippets/Snippets.md b/examples/org.eclipse.swt.snippets/Snippets.md index 08cd32f387c..9f3e1becfdd 100644 --- a/examples/org.eclipse.swt.snippets/Snippets.md +++ b/examples/org.eclipse.swt.snippets/Snippets.md @@ -198,6 +198,7 @@ To contribute a new snippet, [create a snippet contribution as a pull request](h - [draw 2 polylines with different line attributes](https://github.com/eclipse-platform/eclipse.platform.swt/tree/master/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet252.java) – [(preview)](https://github.com/eclipse-platform/eclipse.platform.swt/blob/master/examples/org.eclipse.swt.snippets/previews/Snippet252.png "Preview for Snippet 252") - [draw lines with configurable line width, scaling and rotation](https://github.com/eclipse-platform/eclipse.platform.swt/tree/master/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet381.java) – [(preview)](https://github.com/eclipse-platform/eclipse.platform.swt/blob/master/examples/org.eclipse.swt.snippets/previews/Snippet381.png "Preview for Snippet 381") - [crop and scale images via source and destination values](https://github.com/eclipse-platform/eclipse.platform.swt/tree/master/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet389.java) – [(preview)](https://github.com/eclipse-platform/eclipse.platform.swt/blob/master/examples/org.eclipse.swt.snippets/previews/Snippet389.png "Preview for Snippet 389") +- [render different types of text with GDI vs. GDI+ (Windows-only)](https://github.com/eclipse-platform/eclipse.platform.swt/tree/master/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet395.java) – [(preview)](https://github.com/eclipse-platform/eclipse.platform.swt/blob/master/examples/org.eclipse.swt.snippets/previews/Snippet395.png "Preview for Snippet 395") ### **Gesture, Touch support** - [create a shell and listen for TouchEvents](https://github.com/eclipse-platform/eclipse.platform.swt/tree/master/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet352.java) diff --git a/examples/org.eclipse.swt.snippets/previews/Snippet395.png b/examples/org.eclipse.swt.snippets/previews/Snippet395.png new file mode 100644 index 0000000000000000000000000000000000000000..b802778b031b7cc1f2ec63d3a34ec2a616d36979 GIT binary patch literal 38049 zcmbrm2UJsC_a+`+3o0TuKt;fgbftF$MVf&0PDG?P={3aiVgUiAN)6H>K&S~lSOBGk z9(t4(NPqw#1QL?W#rK=F=9~HcGr#%IT7*OHJ@?eTpZ)B8_T}9p11*l@7mtHLAPybv z`^F&9Ujrb}LFc1KfGf(r*hru_;BTy@0jlV`vqj zvkq$=zFH?Ii?-bPD|+6qq51j(ITS*l#ErsOyD*W|?&Vb!ZWN1V214d|agS6scblzh ziM3BoS`T!3cV7CdZS?HB`#o2c|B6@H{si0^4i{71_?~02PT7+s6i&Am0=s`H6O>O7^R`!zGB=3GI0noGy3F6 zdz0i_^Sq+c&kv5CS`0YsHvhi%3HrC!qBie%D(nGOAb&G*uMfrwc49Fswt9WEhG%B% zkLFKvEp?*r(FC$*^gyep-DtJ*8O?XoJp_XGGR)A!g|v;R64H_WMa-@BK5dnnvxTj! z3nk|wwjZfVar7D68$T9K1UGD)m^>m_Z2iI3YZ7S@Dz%kanZssXFsf2%AG<|%?aQaW zloE)1*(GNJckYT{CPhYWs*ub(TV++4mRG!iS%o{*J5OR=Q}JHK=mBKbQjYv@-_rWRoytp8D0DPz$Gsi&2+=mwpL5$q z;^B11aPye*OTwXKpTby}5H^t%iegT%F@0zftOfK^6#~j20`jBkHacF{T;w2P%iX)l ze@`XVvWCLopK1I}WXp`P1)b#wayda@#Wduv7^*ER4<~(tQ8$*hTxTT zX$*=b0E75MTYNa;?lH=FCL%CLA+m;GvFO)V9Ig>9coTfXr7=1>l7M}ft|{deoSD<` z_8jY#*7c>~yBs}nyuQQqkN}`d*zmrNs%*#lMBF1y{4Tk~t1?2_0$T~Lv^yQgs@i&~ z^-@puIg@-m;LVYx>^1^pM`wJ7Zu@`oP(jv)fggEJ;PyCHFS%-{7$&Xar%7QNxSbBU za}AMhS2CR40DUyP%SUQVgez39~g6<`%8BwVyp^LHU8M6A<=Y^(z(AK;vW@v@Z zlkhJarDHe26lcEXg0?AOSB%RC4Vf}}1qB0UCe|-1P?0+2jgi*lGiK#5XX2ZZ7;|!8 zE6$UimF0}6Jmt=TFtAaT_b$i@ok&s`OUi1ywiMt4q1cL)*JC|#7miD^I#{T6u3*Xz zOc7Q}+gWFFatU~+U55~DaFR_ErVb=V?nK=;&3O&hWhi#wZr2@kpP}3V3BQqY?h!(u@;}X_CGwsO1hcmfS!3=IVGTc)= zv$A)w1&3{<`q)LGK_#D|#e$9k!%b-V!M?e0m3YpjpJQyv7in*t=Pvf7xiMCh$!d|N zuqK9PP5qKT3SG?l4W)guno4@a+MXLoW!2G`zY#(Iz* zEb{CeHI;Q=O+nQ|7O{Tqoxn&qj;g{H{|4^iYz9_`t~2T>U6Y4kKinx&LsGO7!z}TX zM#{_k*HvuohW4w{W_iJqay$)mNh*)@1CwWT-MS8&Uq}k+o6{Pme0t-zH)Hm@1P`iF zn2xA;gj3>KSdDa;HDhScc1EKulw=jkq1QJY%`lo`b=yWUV7f%>MnU!5vk^JH8@xtn z@;A1viLHlrfks8mrSrGw$>FfyA2lZ1wgYd&jFSz^{Z8W>%gx#9l5zP}nx4aM<1|Aa z5~SeQ;DQhXI#XZ3+7g)Af{2Pms;7z@CQ}AKjrR2wSU}a)B3CqVcWL{pC7`yQE6&_h z@Ha8hI6N>wicHNVg=; zDVW}aSb{1s&xYYWz#~dvdg*NVL{BMKGfz1FO%w5CGcR`P=S&kGL0m;JN>sN8;y-0v z#|irQ(>+=tmdSJ*=C{L)00JqaJ+6xuOVeWQ;J3!ppf21#BFT7kqdSH1as&AFi2|k9 zTwv6|lsuAV2i&H~f@N=o$*Cw!ezLiv>d)t5vy(U`vXw+{wWx9(rVjAq;68xmbFR@^ zOTZ>c|-8QTD8pHOh4QnrVBzw-=fB{ zM0IFuz*J}FHmDIMBt~}dRvl|QZonjPO{G3N-1k$XBq4R;5PExS+h(U>b0pnj)wh0? z;6(x>A|0p}75$}Q0*9k6h>aXIXuEZ5gfm+|5ykRLTfV@U-^jPRWC@l*j=)FvWUj8% z%jUJx-;&%+!s+%c1K$aZHIqnG$s^X;wxK`p4Efs&h6t0somSK%4>A6++xc43P#?b1 zV=`5m=FV98^ddm$xdBS~xp|9vt%n%Z46?AQW->pG8w^(7@Pc&C;RfeO!iUCK6m$iT zK)lL^R|`=E3T&X>Od{=i{69TCp?v z=;R%veK{t!km&p^vMSdUM6lkt3q@s>VbnZb2qD1NCMdA{Q|2#ym0eEgUS~V=TDF&A zD=B=7{Vckyd9$mcqIB-tv?8U%L1p>)=BouW#hFC%pp)bipEU^loDZ;30Ypr_Zh- zgivdr(Q52T29#ffUu*gF08i^Wo%X#`O;`bI(D{b*9Gz~HEenTx^i`ds`4M5XVK>It z@9=g;dl1zdlFju)=x)YNOv|lh+iP?+&diWbkSv!K5gLvBym1j;83V zqeN?%09#5pDX^PS?K3r)*w;F>l^4e;(2vvI`&1Ykkl(ZQ-XJuR_3?W=SLaqtcEj@S zd<~5uA$AU`B{L(%9k6}w8IrHvd1M0hJoNPL#tDa4S~W@`f>onaa(~whyC*}Tgm6#J zsHMEE+ubcaIJ?DNRoW4P!wr7Ax1KAM>Z9@t;FnUFcX zu=>VQFm3Bo3iFxzMoW0@o)$C*)7NZ18sCJ#K-Q2m%n1vbepr9}^+;2+-?CW?qYgn> zML^70EBFU76rZX30>g;Cyg&GX-odNE-+_e>ol>Ke3{5n-7*_S7_fpaJE36{bKx;K- zFjJrpsW!5Q_vSIttLC(zyo-mL`ao9=W9ZME1S)hBW_BkmC`8yU7h`WsLffE~(wl*b z?nEQE1$qjjwZrPILw;B8X|adVJ)os1^mfriQ;|MeexsDXqJn#pMRSSN3MT zVFPJHth+$laM}p)1ryJBxj&UaGR=%(g0a;e#G}_ARKdV4dudPZHt)R&-s;0LO-b^d z3%z3YHgwMY35n_1gw{6}{)Fxl+hx&P%XfYr3xP7EQll3*EwGt6V!6%vX!=>f=uTwy zX20B<-QR>#)txV#+^~y!&=4&j`g<=HHJG?a!HojQYQpGQhNVE}QmzY8OjzL?5xRru z@Kw1j!^rLTS7qYJWN^s6{iO(;qxtX*U77-oPNOH+w9cp%f*ZEF+Z}z0EI@1lb>brS zLDzz+powy0K>~aRm83tLDp$cmo)l0m-d`00$xu5Xa$z&6B2v~wX7vWCxp)W6>SGzp z-lT>xJ)o3V);4si6U7FqH*svwxgF87FjXSVjEm|Cm7RQ}qOPuhStKzv6H1E$Oec{y zy!LRkGdM_^pk&X%^5LEvkC>mEe|3(U6DQoAU(3DK4Z|MWZ>rn%Tc~JwH9;=unJolt3E`40Y|s)El3azne*LY!rRy_DytJF>Ost!bst(iBD|)H zXYNaDn-m~!-$u;%6gML@+iZI=nM}5J*uJ2B)5?}8pHa0P*;m4=31#2dWPTmuQ``Ay zoV_n7NwgAH%UGw{?)b;qJ5%+cdTPwGYF4(pExvOp%wL?`H*^32k7lIJhEvaxqoBXo z8k6ioZz+5k2cD2>51V0xF}?_h5}-=i!}iyp5lnv+MXCtexYN`GrCLUA?ik7+@V0-$ zDIhw^7}HWSKCxowT`8i&nuW1EeYpmkjuW$aQ*j~GwOwMu*@ul&8zFeSivjCZ_1#UZ zs>x2j`~AV+_f%-{tPR8H$!0)P2RUxdm1T!_Znw*|UMH@9dGeUGubw~;N!M4WhYCaJ zGqZtIcxq9!<0e0zV@`g$VWV%71a(vY)2Ee+&OQkJz6PzSKeKA@zu2(J^igsY2r9V)JO(a#z)tqlphD9yByd^@aHtvO}P|-C*_5C_X29_cl?+ z7@V-i9MBlIoF)txc-{WL&1W+A4%hj7pmP@N1TI@3=RTpT&7~w> zL_^Xr50!;^1CM#~_1b&bxV-M+Je{sESZ>aJKfGwbM^^wkn-R9R;lssm7-13*?L=+y z;Wotf+4!HhK?`GhGK{{8qOAHrn|6Nc`-GGE9o7V|F3$-t-g*NXAi?ebw_ZH9(52P| z!_P=h9R0n`=YxYwK*w3hnGI^hb#+MCY$_xkQ3=!Ft_=Epnj-}(?qK;JY-L80@jbP&mKfG zjdu(6HxHywtI#1-- z@m|p8arvBGw8SEIYHcByeQJX)ky|kL%_!(+b|{(Ezl&#bYF-@#GrOTW&}E7CtyI<~ zc<`*D^5@_d_?F>2I%U;ju`!h4Zq?PkZ;ST@vq^0ukyc@Zg5&37eUG)z$5$cIvWXW)N+vt6dX=n5kj(D)Pj-j{GKu})>q!JO$Z6g zB#}lD(8Yx9HMgO=Pz|(Ss4l<+0oPXRNQ8N=2;ex09Eqf((KhI?k`L5<%h_ej7N)ve zh7oSHa0*!8H|hJ0B_v)nRzSYpUK`H?yo?*GET(r06=;9F3S4#`MduLkJ~cx+G)m&| z&D=+YEe}|O>BGqoUDnL-37&s-WxB!xqLCjpv4WK%QlLf`^5Sa#147WmVP;aMU+ zy2((Odu)+)oWIH{M>3|>u1~%t`RutTepSDP4Gd#ezSl&|h8Snr!PfU2MHb?>8PI!z z5v^SC!Npz!AQbl#t!8@qZqw9V+IPKztr_#TJ-xjP(4{$O9-%#uG0L+wN=WUUO=r@v zSPC^V;_d+8iA0x_0leo9#hI=FK_xegAo6WP!$&^OKT`dAoASyd1zAr)?{uVYksZ;N zr;nn-pbMLSHbY5O;H@Ygi3mj6E;0#T_)Q#m-BJW!j-^xx7oS{q36u52W^3VYLt7ee0ux zrD+q*<3I7_==-uhP*m#^u~<-g#of)P07ig= zZFWyDWFa2V!=a>3%1}va7h$9Z9fqGYeD=7JvN!u3p3a(Djpn%+dEAA^AuwX+Idd74 zU9w?tKzA>j`tkYZhaT~l;;u#6xW#JmJz@Eyxu`P+9pw}1IHK*ufj}vk z!D+NcYIxmYFV3Hnu~d!iGIndVfoX%H;_`6a{B%HRkOX<+>Fd2I+AND} zO=PW7CM{LTeJg`;s5#hXe+Y^ibl6QfcaxAw6%1+pAI#n3y=6=nX z58i*6GTg-@5S2~zFf$&vH>0~YNABj?I}p{Z9q?+N5RSZkqN5RA@>~(= zviWhUgyNUxn1s;D^7<@f2-MZGw`ir}wDei^1)HCFp{ibKm#sPW^h?Ze%`PJr=nuDy zifwklB~Ept<-ezaFre2Mt*ydg21Gc0e*Mrb)dR8NufUTL8)^$ZHZg|D>7`TYrJi4} zb&ih<_Y_68pq`iiRE`c482J?FF#xK{MP%1zp%%2>2b=mxw8ktS|v33C8;vi zPUYIhaT|fUCM$l`kw_ z`+N4-tf-gM6%0YVhRempzq8iy)zW(NS=N$|yMxv#Br~P50jqdQbltk_^iHF7(*0&J zSZC7%6?}cRB1pDlQG#z}?DB+C>_|~<<;zE<0 zaCAYG%7-V6=T^nE+F;ou(&eXyEwVNg`MIcvGUAUkK>6i~Hr8idLfG#h#vcgWL|0Ec zbsiZg^_yUi4z9c^cW?si1OeH63MEOj6qZMX5P6`!3S2$1p%_`juMF*XsI=e{W3PM8 z+LM0He@7);SgRvcsdx<=d77dpEuMONi?d#-?YweU0M0@{0%#Thu{9RC2SA|bv3E~# z0N4J$|9>t_mEQK*_kXl}c!%mc|FU|4E8w?w-DUz^2= zg#Xs&>l`|-#5MG>T<#dqfszL0vSPTpR-<#0Wsgv*h_WOdHyj-tUZ&@BG8Ksz*G0&2 z@t7aUFm?dX1t;px@FAv}pQ>B_?wFO+q<{LYbLYN;hht`NHrMI2_et^vCdb?sDXRh(xa05&p@qoy*)ZP_ zbYG?qfop%(5r^0Y#<4Q~f+ejv&+A9GB^QJQ+E2W$HvO37Ij-A&M7lspacDt*`bX(0 z{|+vw_?6yf`)tYCW&DpQRJ51)rHvK6gcZ{})87q3jUPoPXL9{!FPTMdCcO=d&#P{h z7Ek6gbbu}1;pzCO%eT=J6I?K{qvFb1H6*r8qhv)}fYYnTsN*MdZ!EVBxd%t~*vroz za?AeJThk&;Z|+;coHJ29E`miG&zOFEFCF>W?rg*R1jU@17=?wY8*3}XbR!K+`;B&( ziH4N0*n>&kKrZv|{tcPp?hi~7YR+T~4|@tlBVCG;E=3yo>Wu!K@iM{4uPfuKpO(wa zihoDaaF!H4D@Pj6uGJ`=XjwKVUv1WLLq{Zx+!qPCC9adgxZfrYERPq{pC_IW$F+5V{fL8Qe9v-adejwA%Z88>JbOp)O>@qDZsJhMeA zSEgL4z@HH=5PFImoIdCh*!50&PU2*0hbu)$L56tf3(}dCLiibEk-?_?rTjWyzZEKB zq$q!lP+oTS2TsR*EMqcPxYNkXHc;VLnJM;EEmX(2DO>f|djVh+VrMVi?^MfYc!QP& znVDzU3g@ksIJlukSbqh(;h&q*M{gwis(tuGuJ{@@t_WR>TgzM)E;I_rYPiPrYR+9W zOEKJHj;FfI{yf%B?i2zIO>h#nmU9d~nzQ7X9Z@djMmX{p7yK&FsU}O09ljTXpvSSO}7{c1!+Kq{=x1i}u+!CQU*JH0fk2f?nv08zn*i*nxu!Vg0lNG{ zXL*+Lm5t9v0?r=Amjuzg0!%5LOb762#3Hxq#jFJ3$&&|mtsdEuOIM({eEpvyzwPpbL1-(ok9>=6!DdsqsZ{XI4GH;RzRf#q@hG(B z;xg)^tg8W^e|AgGwK~F~pZ5KyN&Y)O4s$hDC705skjc@9AzBeJo(okfeu1_;h0Ya; zVIi%h(#R`hT-%+w0e?iyEIByu8RRkX*ooZoV^jgzpSMa5DmGc}FlZ?|jcnNuC)x3E zp$(ou6>OUYm$Sr@Hun9QK7YB?ZlM~Megn%nUKvBQ?b|)M#X&=UIv)Sjv)A@bZ|(H; zSbISVFlu}ME-}?|RJsb^q=SLcobtFX$3vmCpF$`HFm~eoMMuslB$pRzW9{S%b?N7; zqW|Dtp>lEc&6~QcrAKLB)h7HOy9XUKKd)~S>bbtau&_5fItJcSvlnAnQsh3_+(nba$<`)EbGYiNvcBS?QBcE9GrGT1;BW1=J5g&W zU2uZ`iP-nktMGnkRd&|#NRjf2$b*aDgK<%&u)+RVi_UR&MdP5h19*`flI{Wj3u7}E z;_W7~s|!}5uC+H7gcg?(v+}Bw3TICq_cAWIRuBqTNFAZhnR&sYZuVh#bbZR{+sP0+ zso(?x``IOVRxQJG;eh;ceD2;>Bi6nxbhF06k(?23p@MbLMUwo9Z{v3A#7e2@#lCA@ zYw5pFDg7{)2%k2zj{#A8|{x~Vu5UF~me z!HS$S&hmnEjQ)a%)>kxOtg+6?O(m|DHdacBT(Z0Ay|HrHAnY#z*}EXR*Q z#-tCJ-fi0SvIo!`6)H6tG9EiQ__tj9)2|G@2rZY6f|!O(zqI_dOa*Y`qtb0b{L9tB zhfk_@M*XTL`x)lM?rH4vq+{plvsTMJI=EfY-a5MB2bjd(?@J#fTYU=5h*+N$dv$tB zS!+JoutKleC6Ib|8Fm}fs+zaybPP@AnhI{nX($_M-OJSH_#R-)ljTUszL)1ce(8dc zzR8>u0|%ky`ZXN03hZ_ItluBm{F1sHxNjKP<@q@=T@K5fr8s45_bwi<^07=ssbGFR zCVCPd=nTF2E1f#9Sv7JdfG-_ypo%FcHrfx2nv!Hr2dtG&3&5!s6Nr+Jki%8dA8kyZ z6m}mKf7!upy0(h(G59v)qY{DmVoi;9Z}zuYwKsLNHJdc&wRuIYDh-6kVo71g6b(z| z-$a>WCOYSXTSi%OHdyD;~*56G1lZ{k5C6S}vey_vhcoR&67fm*5 z5DW1ps0AwxIqpWxh{DC`DQjId(dVE>-+n5E`L~Y;{VFq1n4Fb3DYERvQ`;-De?PR2 zD@I86c7c*lisX$~eEs7weVQH=p^~OB5gQk1U)NZrkEFwoNci@R-b_(tg)Z2^Y{)0_ z1!-)x^v91!o*XppARWuO$e_KShEKFk!bV>-`3Q;p%x-~yf2NThYG>s{0T@U~A8Rb8 zlwxNt@mSmgDTf(dmt+irp?tk=UbHI zcnP}ENZx&I?cOW{jLPaEyiz6{8)|@3D?ey*kO`lSw3b2660}qMrqTwVSLqs?{c3>Y z8=L^`I4U1JvKB8xV~=c=sYH~{hHW&`*@n~Ra;gp|W1p%9drbMX>{Wb8-`@v(?LTvpa!oX{L^2Db@pK7iFbA9yK|M6ssg&XMI+9LtC^R+_z4;l$luhknSlUo!&3 zhW!*{lOGIuuL#VWd4EIpPZ^Dv>Apk^p4aN#%!!|aY?glNh{mt3fzXOd#>~fnoXwjy zH{qzYbf@yi+q^+5{2TbB{`dBniS(9?e*aN_-6j3`zhWR-ATw_K^MaWQVcK33w!RW~+ zHVU#X=%`)ctT*XJIk#3C;1+PYS0GgXExI_yg)?O4!JN1nmCs?~XpMp{2xLpH3d2khOOkTCRqvi-87DAVHB2B#YJbqUCBCvbTE~y(w08WMl}I=wnqECsd3ph44L^oegw)S}`^))XFeQk+Alvm`1(# zyWrN=gUtStKyCLZ%0HGvR;*;fJtL29l{dEq0xC(g7=EZ%2nu*;_V{pN5Z15mFHdYQy zLqu$rhU7FI=Q_A`|44|L=3}&(X_K1lAXsK(n=7Dig+05v%pTT|chC^U7B5!ZY;=Vt z(sTqqBQinRIzUn~tYJbEP3iWgMr&qy<*YGTZIwB%2j4n}=W$8qQ%Xd>@L!jXOw0YX z#!zP*vXhXBnle0ZhA+(a=XnMmKk$`ppigjtbW+}jBcS(I)e_UUM*8=>WBZdkS*Bmf zvJQ1#_EF5h!Vlp*F}pVgYzTUaK8B{AQot%^INFw)7!_zdLf6r&Z)Q$?oqcnF)0LGG zHIis)Re4Gp8`VqzPJw>1j^u|wIj`ej@bwT zB=u15{$ifKt@Ur*=AeZvAx-ZvsS~~i85LyC1};bn7s`KsvQMsZ@w|7GeKy)VC|ggm zMC$hiHmPu%njH6q%=gvKMfjD639*wK8-s-`*1l&2T1KvkA5up3AV+p6Hd+~NbjNE9 zGZQcHfilkJ-r3!y!8FDNK{i=ePxS?-EM$-Y1o6e4dR(v*H!TYnCO=}>n+Dp-Owi)J z@`k1CO?Jq`Kkh`)GoBo64mRg)YABznqVFr;J+n1NBxB4Bk^0Ng=pg-A9&JiG5RlLx zbspGF0mhP6@8;+afXi0M$*iQ-+I#U<3V9YhnF|Z^ebs7%a;@1uDE&PAPNljmaRzNg ze}U!oX&(5Y8^Bm0yL6##YWuuE&wIbLoCjSTn!Vh(*TlhAn2?PKEkSaCDi!K^4&D{< z^i*U62w3Ge&yauqID7j3LEyrb|5%tYg5qE>x})7ER`e)tx3Hn)7Hxix292B#50D*j z_6CR|C@8ZO*S8^MVNM}qnf2}kU0*_2r7Ig^ zV2^Jo(4DI`S-j*`dt~uC;EsMpx<$1S%Pc>y2vihL%_s&5n|Ib>+orsuyL_Xd;v+s} zgqy{JuWUs!=WL{Fka#YL{yw;78<&&n#EBHTqzPeRk4`hjXce}FEDipI#1A!g;nf5ogps0U0(pg_r z_>RBiR-(5_J9wBf71&ar#wxQeCyD~CJh2P&udh`JHVSJg(G&Z1Z>&3kzvc!0^MLP2BUFYKJh-Q1>7h0y$m=pA$X1xtGoLj1 z9O^LK?2?ZD27Y|XE*?#P$C<8~ars{qbFc7;{=*+?wRO@}A?9p_&IiF}Sdo3dI;3KO zhm^;Ijrm3oT#TrZs!bej?3-FuNNy>NMi=uiB)%7(t7tJ%O#a|(k7EYc#X`k>^&REl zfh@@pR&e!RgU$XhGK@lD$~i@o-KDi3{;V17^{b_lIh=%$5BHl#%x!~>!_USiHB@~B z_pvW4pY~Pxz#K-%_pxpbS5`xHTga8qgYbz(PHC8lk=FJi1< zRmdg^l_3&WS6#7dUNza#%yh?jbnQ}|?4b+P11woecDVn{Uw!wCC=KiG-nRUo*9_y* zp@L4z!Nf5`U~E01fib-vmt9+fF_6J&7;C3lBd-1Z!5*B^=ZecTpWqhs3KdvRgbkJX z5WT&tCM3eyu8NSNOSPkdk0Xq|3YvY`o$`Iryx(6GEwr8&nQr4fnxtVhkg;!Doe)Sp zpQsx}Q>b{)g2v;B=Kmg9AeV}l2x0iTva^i+>erF)q2PpoKM{q+Yb8o9eM&qL<~(r$ zZa1qe@t2OocAwsNe>Yl3@PS&vu-0N*Zw>Rutf(-iV>yyUU?gvQxIYD78ENcOo`jdu zt$ncf#q;v%vK||&gIJlozq4bMpi9zugID$XH@p{!y>#2^z4!(~1NHa>wA`c7-U0v3 zO-kIZ%=N7Fs5_*Ae({6k%&t+}R5B*qd!uaar$1#2xRnA1MsL>%)fd z3MGIs<`KV~r+Wj2QjbP-GzKj8B^~Lp@TjZTVOG5ujDkV*f;lrsgz%w!P~UoKS-9cP z*-58Ap^@F~8(f>CQ@ZA`ghn{3x{qVd!1$YUu5JG%bKcbJC3c1a&uA6T+G;jW^`lKN z&@!`ayF4{g7qsEX_5#=P>jZ zu(dJ+kNF*b?0z`zC9X)9MChZd%vbf&6|8phR(Lbgs(qF#ltrK$JTjThdC__zt}vO& zjLt;`!x={zVmiaLfk|k>hU`$xh%~Z?$(3JIbQPFKsU(km@B403B6Fb|PkIVuuziC_ z?#P$M!uem!`Tw15B6adM^i4^{}KXUN>;pJn#?zlWW z-gFWD!EF0${aT~p&TCp}VaFxfrj^6dVQtn(Z6jLo90t+{t*Zf62x|k2dw>YkNhl|~ ztS$AWiQ}Cwm|)YCjQJX3Z0KPg1v!j24TW-g{g$t$J_cOA{cKFNI*eFBcl<;|bVNiE zx(Bp*5p8(?7G-}U^QrmzX7_3I-XTU-S>b48y<=cbKI6%jih<^e zLtK?%mR}%E-vu8XZx7K#ZWgZ9`fYVrzzfs-f7a1=tWJ`a2R^m@gN*MT!ybSn#8a z4_(<9nZrF%7BL-WkBCgbfg$DZPLC4vEPbN93z`+dfFOFj9T06N4M&{`J+&8qUAJ*rpsdnttE_hix(+3 zGi|?EiWVm7CZSc%LJf}TySbzB?e`ypN4`^L1Mwd3GDB}YH0!@KdLG-A(OAQ}7uY<_ zHw*=c^|Us0#B|a^UIroM@%870Kvd^BB_S0Td+pB^fqD?YJ#tDW!SlJwCy=Cs`Nz*0Ji-lbTWzZNq-(g@9<;Xt0br*+{?N(t~QY(^w)7bG(hO zsEnVL8JEfXo{MV{bA?fmh|UA6(3;A>xXDLc1Hn*r@T zB?+>9olZscLj@PeQ{|3;9ftF3t=9|V8y~97vC9;x`aTDs?GUpDr=~{jr0sf8SR#K* zL~e!$Zbzv&Z}cSqaWuh#7>)&VZzn6eTbC?%NLQx`)jR?DM12l=f#?@2dvjti8JsxLYCZ2@WdNbJ^x3{Sb_XFdr_9NqF+{?%4{X3%z<}GZUU? zJ*VGg_geSo;m?r&r(Ng^k%6{t)1BzgQtf+{`I7NZDaXco`6&dVc_XJXp#fBR8pu)O z_$Q3`zI6E#Kr=ym|B=N0>*C=^r8f{V(h4|%0Idj*es<~2C4hZhaLwgRo@}|8{o@on z2U^!i$Ezg@CGa2Knx~mJP^vDi0KBgPx~qNYKNTNwyIHuO&=p4ksqWp!SDqgqa2*!? z>$%;F5Lar+_Lr{`ksC2(e<-%Y|88{u%RSe=y~?ZK$j+Z%U;8Ghr|*%d6&T=GK8tTG z(AiIZ^fP~-1+fp`~;jz4v)(z3cR zxxk(x;4NbI7bxfO(cA-`CSLBO%%PSi-<1*L{`W3kR4lRz{v5LUx^P6|i7V(X92m{m zIr6vDn!u|jk4yi4gKAC7{Y_Zr9aNBeVsA4r_z2d~;>1aEtEjQ_KEXHaas}dO{O#jg z!_toQoAHgSaqfQYV<$jk$rn%LdKEmm(;m&Kw_FySK@AoduPw6<1bGVJPo}&a(!T%k zhk6#-Gg~0e6)Ay;P(?&UnlXk1&BWq>OG`Q43KX*SDr_`6`j`3OjLUGiw>dds)cc_x zW<@MXtlYI%hjgAm{76{xU)xckEReh6c?eC5Z>UQlMU!i}(yJN3$EU<}rZ3t7 z=T_ZrzNQxyKAKP8@r`&C)HnKgYU+_b-G{sVH!BZo=7Av-o$iO zij+L`)`(gkHW!vHgv1#1)nplawv~^U4`|xF^7Y}%YaMU>aSK!E6d3FJ#pXtu(4n7w zs)=ct$M5(*f`PuieURsT8nkkpxp69}+Eu!AS;WGLFKl!we_v~R%kHPDT7D8a(*N4i zdh~hH&xNFJG56ZZvi`FCAr$#>@&y1DGIHKsZagVMt?O?wTun&I8hSWh?VC7jSaQ$g zBK!xZ@1Q&oFS_iM9|hC}^@fYWFd0tej#-1n4~BsNX3%V_V!HJ^EgZ~Sp04@AyH~;^!rlzxt3t51*)7k4cF6RShMd9mOTfP4Y z4%GhJsz&@~|BqPs@hnG<_x}K#R|J8hBarKze>*Jt*O}4(XQ6MEpu&Zn_5=a(RST~J;n#9JG+8MhPU zLuK|+H8mU`5Mk(ad3tn4NZ|l^BG#?9!~%24+oCAHA)K?|4OLpOq^9MR26ipjfB-fF zl9}p1GViEGJi^Z-TgFh%0foC2biFy5CELPKoGR?%a*+^}2=k`B_MXb{pV%t)(H?BD(ytH= z-TX{kMp-bTVvp36*KmT`Du(Z$T0ITb<+C0=X#VlQq2-n`Gr1pq_+)fYj}F2$C6PxZ z*tQd+L-4f7$Zr9*!+LOQ>(XvN=y{5V{wXhvyKt!WD_=a-)7o66gg-mXoc5xDt1a%) zaX)aNl>F#T87rBLZ&nLg8Kbc>BRj7-f@K;W|0wAXst32E57}Nx{dR2Z+m?r4{5LOR zMdd+IP~Od#ONV0v6kcpTPfDxI^s_0cI34)3xr9Hmp>KgA?)JdMnG2+JHzUr@W@N$M zaAqreuF=I@YU_Q|ZWmxaz4^)Ydr$1-B&-P|QfmqRHdiF9v)in%(8aKYjy%9#c~4r@ znnq6_05v_FCyc;%4I^gHIybCjphj3<$<|=7oScHdUzdhjHJd7Fnfl#?bfYH&qd9}s zjcddJZ;kd!MXn)Fu)*1sqO8Gc1MSombuRA8Sk(ib3jflkFKYZ>4Y*?;$UqiK%kE*) zGq!dy(AKnM*Z2^`nQ8V$^b>DD(?CJlqlX5@6?#PjJitx#E8m2A8$z)B zb{j>*Rkw4=1}&ap?*mQ(^*!134-I5zy2>SA1CkAHa%}=X zyU{BQRBYoOerzE9eEMysE2xQUqkpYN;SZZ?6W91Z=dAn}(pvrtRn9epQQVnlVLN|Y ziPIOoDCqU(Q7pDse}8mw|MSvhC;vI07X5eR@yk6hEC#%!rwOVQIR!v10KCA{Vh{dr zrjQc~pw9_RM%2Z)6WyXR<@)?113&AcVIG^~_=)*}=<40y+6;&}-!}j;_>)OD0bRIv ziX+F3T!SB`_t@7w!oQ{so7h|b{@tPwh(wv~*$x4esHryB_@NTQqNu>$C#z1U#m`$? zLI7TaDRm4f4)@R6oIV5^3j`>iw41(&UJF6Zmfx_K{|_Hz?WN=oCez z8-|Ztf*h?I_l$e*w&r)8A2qKv?Tq;g)V2ns80F|NMQRtL*CytTfY*M%&MoDiT~ZxZ zp}~H5@j<4rWnJODe1yBfkM~m@Tn-4?EcJ)z7G(? z@`w}Z0^)V!{ilZITT&6$~`mjj-R{D;4*!mK)7Xith`mE7`->{mh$?nnswRn1kxO?E{+R8f!m` z%&fLBug&BqR*#_oQ}te}w;#}4AY%hoJ_jp*i@ucP4e&)g*}7$l_ru}=&{!`fzD zsJ>ibK{ro4*GsFqeUMKvf2lfvD*S0NUnWl)k!p#m<{k1ge)y7ZV`G)@+Iu;@$$Is| zw|No0#%9H}e4lf)$5$?bez~ik;&?1a?uCfcAN{^Joxv+yv9w5z0$E4xG=0*uqcupX ze1FIxGzNDGORbgMEiI(Cgkqwq=dvV}=*QMbfKYHylC6)#IRGra#f=|uW=K^Lsy-=E zKxP+je-gL!AeV`#nf7|6$({BmecyycTq^8cl99Sz5gDMdm&f5f&d+TwSi*)pH5EJ3 z%~N#YBLy(Cqkm6F;ddSQY#Yl`Bh&`uism{~l?B{AO~Q+$Ra)}9ojCSrQfl|lOTU)U z&sMHbkn24Nsw6IucbzSA#q{STbxUpXfP^Q2A1>cFXs`u-9{en+x>&+*RZuS8d!0K= zRzYDJG`0zJpWQyC;Wpmo8{gr>u}{9i6Lh<7z>@9Q4X$BSE}}}94!%Dd zt(XUS>8*Zd`%bk!tp!I{G5?dESP1|RupA%$RRB!&5z1BCo%=vr#a-oE`iHaonL)MZ z)%P=lPM!IGD~w;M*Or_17%SSq%lKn!$+bTVoua(K`q$=wA+&i9K0ehF^_|TL@5#~8 zyWeeF#~AZZkCi`VZvkmpR|kcFV@=@4YG&^(z#gjhUZ5Ptk(Q!2Y=pN{b*-``Q{@=B zOhyXD#7h}?{<*`em##Y2fJ3CZ;HR)4sU!A2Q{wP+!mM zbMKzhzxMZ;?5$&ZXJhgPwJkPYy{IzX?L5lMGaOvEvHx)LRTyK%g{-!9Pwi<+cWbB( zLqZwxC(82NPWXSYs{^j4LlzZXid$t3I%wcuO<;HaWQ_s-&Hv_*^1pCTB?W`;mE0f6 zfz4fIkw0-9%l{b8`PapdI9fTb3%Z#IlkRrOAa6*1e}_e#f9FS6&>xLF-EzL{zwo@(Ol3*#RvG;Z$I#o8`7a2cdz=BQpfQZ)bdtwE9)Y2r^ZEx>}?&*_b~oBcBF@-tR_ zX&wcHcD#AzR=)|F<(DbnM1?K5*U+1Af7)G?=Dy!Oc;DOTU7ENdkjZ#8)yViy3`Xv^ zxW0sIDDK9B-`P!YS)Z`o4-VgnG2OuZ^n(28r}6a4R&we$%)7q=rU)|()=}$^f6kPPvW?Me<=g<6ay0Nf+i9l zd>onTdD%$iQgc49fjX1w=_Gx*d-XOmNl|(s|5=FqLc66(#^_j5ljOeAWt+K$o0}8> zP9o^8o(%VW8^h(+4DZv#L2a!E+mCG%3R<7;aBf(gHHfTBHaFkr$^{=aS_8{=UVPKo z-F$8`x*r41aN)!LTFx(=@~Sbe9uB|fxbN=2y#L>d`wFC{?-925L0s z1`K@Ej%U2TD>1Yy&zM`*8Xc%mLK6aY`p?Dl!^Gb&o;y`P7f*DUCWOb;m;K&+o*5iA zoO(I!R!M_KFZJ%V8kx3fx+&`FTJyclg`-Non#Orv%*FQowprG~NuFzI36(6J0aFecJxQ%HFaf_cW zAU~t5ahqBe+>M(z1rfu!x)Yct@Wyybw0|;VHkapIIjvh?YiX ziD#CEcXzY6$Y!0S8LqNi`q^kcy|K9QYAfmbp;*a1IV#z=@evD&Q|Zq18O_L+o1D}A zdd*16XO z1O)!PmE#R1gWC>}36;mdQhV{21)D=iXyW5h+v58dTGM~#ArIZxxjpVp^z|A1xxIpS zHV=>(kK}aA85g<>XXrY*x(fft-RfVv;W{E{;D%1)%>7Rc)c|Zy7tHw7PRU}q>y2b% z;(Hz#O!F#GL=$5i79-aNgVH;8+~(jqJFfHjsPaKmJXqbp&k?u(5CSUw&R%VJ|2e56MCM2nJ65&D!K9&OH z1=DPeslaXjdWlBtIB`p7hor9#GI&tOhB$V)yTuthnrDAzjIrIe zbJp6dCF?k>?redGNKqjwLjH<1f)AW{;~K&EOCzj)ekkE%(S%x+wzbgmDyHPkmC~#@ z^U3trsv~!s_3k397pM&2W|{lh`xUzd)sv1)aIA5scV(_pWxZDOC4V6KCZd@4<4Gqm z#^TT9XX%WXBv;-cNoJQSQ1(+dGqRuxznQHvOefWraZc2SIAMWjn=;8Qt|FYKWd#f& zbu-v_P}|5jp4R5Bme|pyd%syv_AIjyql&1mfTXf;|F`&_&!Ne0~FVElWvjrRBO23k7nS7{s9KHDfw_4L|NL=f zjk1-O#AEh3SK&t`X;M{7V5zsIJ`|tvdEA|2O+z&bW6HuipDiS$J`XbgMW zHciGkqK%`MCFkVXD@(d4D54=yfXcHBE6+d@W%@d2MI|dIwo}NMpaB`fbH}5cv{`i$ zH6CEA+b5nCTPoRAwl*nXoY1sBiL3bWm%I)pHA`5ZjRALz|O_rE)7iWy3W~z>%0Z?n?TGEpuMMY4$`|=!?7Phj2MhX*l z14u?Rt}YEcee7Hzu1gddVH?E2ml|=hi_o^4%Y@Z$_yPnERxM?iI#4fU(=&`my*BP# zaDDjwX`KzGLkolaf*NOr_L%WhheB7PJ3lr*7*m58iyX{x-nnBGm{%3ir6mMm5)1nk zcYu>6DFvT!N&fa{XTFIe9z^vcDU18NY%>uzkR}yZhQFlYJS;Dt+h<}4=iId$N+zLn z2(+8q(5ninsleFO<~^lapa63tUr9XDyIjp-ZxL)>>~rs!H*ZzbFk3<=iBQ869Ai&T z59(_|T*jwDRDZ$ArCoY8=q4~|yBwt&%cL#4q+Xuu9h7f$hv36r63cDeE{xm?QMJBPsbA-7*mD?t#M-hK}=C$_75ryD{0`P zZ3WWg_}EeQQsI9xxmk@>V8FW5O}Mplp5+9vT=h{f?Fm07Y9z2{U{A~mtM1FUSyTxZ zXM}@|wk}cZT%a8MyY|p=Who;@xK|9X_C4vciK2YGFJ4>tZnq1HvwQ=0SHb9PdI^x@ zIB{MA&oMv1NnZzy+JBo``I}?spRzCDAxSMCKgxdp^ug=zS|xZsJ`D~E%mzBM;H-d! zRd2RtshTg8{#bwG74+r7?_cOCgvWkqtD^FUo+15UkfvC820T#M(^atRu(zHg`>){w z&zX-TOc#7ZsU_%(>CBL8ro&wl^n)M4ly0dBM&C$oJDDBVn$g|A5*gH zCaqXB)A5^11vs8s#&QwI@`cCvwVD^P@5k_|wfR!Va+iihKs0xk)Im#bhR1Hwt3*5) zRt}&RH|;ZBoIldP&bN0r{J=bl`W=9L$yi_(^G?dtrv7fJrA^?8Y)v)V+0KSTC*^OQ z5y9DYQ5OZq4XifR`r1P5mg6fgR0G0i#%?7+odo8Yo$Y%~12^~DcqTydw^)qI-E>3e z`JmS^QEx6(o8NJ02s;nz@Y%rVi2%n-is^`O#29+6KGA%X7=r9o&Q-7Uo7o3MBN#5V zG76Mr^(ec=YIHK1@+Jd8joL>iCV{B1>Ck3#*<)3vu7Z=t4OPCVXKciYsqfd5|gi`n(A; zcy0k{w38e8_cNyPtmDaxtaGz^;o-&?{Jl}-(Tw-F;C3Dfq6*GI9g$DABHC~BOsABb z*d$faL7vsZ;Fy1Ium!HohQI8#k1?DkfxZ_vAj-XbS zi(U)LJB?~W*gLnr6{WgDb{!z#m1cKeg=HxNI!%U&sZ~(ueNdm5;QZM!3W4btB0xB( zG2oSzw0NAQk|_zOijI04=NLux)P@o8yDaxIK6yw3I@Tk&t77U~B1VUc;H4}^8OPys%*4m?#yUT$dnarEQC&UGp6J~IIId%G+t?)R-h(OPIgYGtIV3(4x4XL;gGe;(lZ{H%tci>BR6{)VPpZ`{*n|g(?%C`cfibI zQB#=AGo=I27cZ{JPBtn%$iPBPaRR-<9M5j_ zLnC1pR5JMi*KazWip7r^XVM)t@tNU?Emq0~VXb zPSVIP2cGfUhfn()%s>Eq9TQ9^LYF z$V|LRpev9Wma4bAvzKRC2umth-i4rd+s)IqrXhLkzyjpN6 z87v+Ho{7WS9WHa=gBfs8JBS+cx!lH$9YEDm zSC`8dUlcuFmtt}IRS6xKKEbaee#U!Z=|h>ieH5+dNpp?L1hdU{?K4Owu^uc_a^ky- zF@x>fTb79=onLbu-nHh?QEWds8gV>z}^ylKbzd%`&EEqOMZL*$<7L- z7H~eN9fo7)oH_lCjN>kycH4BQCMW^&CsL(`W;uJ`*zC5N)hk_J1xEdPDXLbZqJ;8cLsnJN)8c`ml5y*bQ!QaJ=nR`VcIq(7xA-^2sXpb+|0#eZ7T#;gBn1foZrYE0 zr0N22Dq#MP!`Cn4W+DhO6{J?!0q$e2PU5FLlKsfBZXD@uOLD@DFU4XoNHu4q1UkuY zTi-l&x}1g?QSO@JaRL+*Tg_m4ma*`f`?GxNQycC>!McH~Vo4!xK8LW`53kox!|2#<7U9Xoi)v6=s>L{HmB^*q-yU~ zRA(+0e%~{DR!|Nmec^~^D42WT{z9lY=ldKr+5C&!m`5e=vDra;-k1)x!B@O@J2ML7 z^vxg2YSU85?|MP_l37w_S@wp=hr_3(&5KR0N!s@E7BR>JPPuEK0mLZQ3&n`q5RY83 zcN!r-o6x;d&?k5Z`cCZs#_3d16gQN0Y^(3Y1au0XOrXxJQPzH?+!6IT8-X?ag?ljb z&qwoIs=#gJL8m~w2M2eDquckvH*&%+u zqkrWh|F0)#@Yw%8C#N*U?LNu9=5vw<9@{;`;wPsF`Wt&f|wS8X~#dODmv1z4e5gng9xt}G) za`_8!S4DMp{CkP%6{#zxLwSNR?bXHvFi(6S$2EQC+`+oJkQ~07JWn|SXE%+Y-X!jr z9~UijUC@YfeJB%-uwPQsOwU_-7qsbQfd|vbP5_YzjhFmY1+(l1vT%85KXt;z}? z5OYt?rAs@T`-V&B^N2}bm_7qve2i{H@QymmCJkH@`*;(GB1({#1RzZ>4$Fl%7YU@Y z2R;IL956j)j!R;i7kMD6^68aZ7@*>+U)jANIxpR_? zFtP`)lR(K#kJINKR@zfzPJWPI_`q~;dr2tvL6k}xcVbO?>zKbTT+N*#uFkkj<`Hz5v~>clo6ecSg~8N#DpPiuC8Q~_Vg- zA1}=aPPIJAninh4eYxN#w~$9p!=Ifr3=b&)fWIWJD1tB6E#BxBW)|OnhP}Vz9tl`` z#tn`jzDub^nu*Jv)!6-+@l2qNAFNv^~z-&6z(pGT({Dq)sfRBvL7hi z4ULXusad%D6RRunvz>^y9AQqEoPJVFwTxIPA6{CI0Sd;sS7&kX9d2z)dt|d6i-!#F z+z#v9uwWpc@7QeB^qW^(SL5!v04M<5@0wS|Ou#aeB+HtrWd-dsClPRxuo#+2uYwp- z2}ji-mdd1y;+|o4yAISfGNG|G3sef#n@POQd4VT8fj_aHA3gIvxlhsJ45xF>GeS&> zckz|M=l>VBhskl9DUJhg15YOAtB673#X4<1c)2;&L3VI$5<7VuB`|4}Ip@s1I|@f} zEZd$zHs_#eqSlAPd``hMWkHig?`g~dtgSpVXFL#s>%!`zNr%4>>Un;P&u;9oVi9VQ z1~R?`1_eSNgz$uF^W-Dz>Uj3w;*^@}Uv-iz8#V7E3MZ?j?FfnnL;Y4jfdR``R2;Ml z<`i`8uB4u9o2hx+5m@Sarg#?wb7UYhUB=xw+*tb66_l#D554Pt`_rD28Jf^0hDiGz zdVK1?xK67fxkaiodJN|I9yId-hCp*MZ7`M4FJ~rNg3JP{Z6YTBd`MUst!g6F*zfnQ zLYy~xgW#v0z(#Z4>p7kqf+|=-Pe8^^YQ?AZd6S-5eXB@NBUt5M{LozYvjCd&hQ697 zr@Y<6W47`EcujUN)7<*TexZX=Pe^Vx#zhFUV0VKJ^Cwj`25A^X9jBtbX7zdwaTysd zJM}?^cynk9uYBgd-HAVdL74(NGMO%KHQD3siE{1-0Ql!qHbkL#J-)3z{xcR>av5my z-)*sshp{kUuUW@S6h@BtSSE3jR|9gg@_oH~RYeb{c$0qNWS1$KgMS zx-8t>#zqgVHm1LdI=HPy^=?7h?o<9?g8*NAe|`bt2z#I+I#lETyM6xm2Jh&h8`a;F z_*R1{S2c}$vHvdi5DQch9Nl$CwzUZ$_qUd~Q+7W4RRD_%Rm?`{ySi)f0iIVR_eo-30w8T}!CowJG)uuW&OaU1n*y&9!m>hTo}L+fmhCUcyXc zTt9Drec(31r6XDzz2!WH6ea6T zDic*?^Tt{?PX|g@vkIjZ!$!G>2eZ5kSZkI$xx>ls)f-B+9BvKj#K^wS?q(Itz0re< z<=08S$kuWd_fMoiOV_q^f{h5Yb*V722AH%^zRnrzF4|S~OE}n4Ul`)j>5>UA-tenj zt192ahe4Bx_tD%CmHz+>f5jp5VR=8RlXx@zoakO@I-^)rf$HO6U=xY4rJVsnOyW(m zQO&K@*co1|3{wT(UKYwyE|MlEgz$?wUzR)7VCH)7$P^P85R_~t#oDThcx^03efz$(`Trx(nthQxzT~pG0n$k>Pn9G)(rv!?}1bNGS84`u4gz?+hsj= z#ptE>c5XiXm3ue=?o4MX(3F!+w#eGT;6?EBu83iiPx(Cj2I+i*!>2t-GC~OpMuf5j zYL>8ei__O*qGI|3=jE$iv(9aGk&p+C$&t^;38uFe*V|m`6aTnz0VZq;c!+6$rvt>V zO-^klrRfiGSd=MK0N&8qfDNBDQVr`*^HMx%BXq(7$Y}m4Fxe%ejg-Ntwasc~B!_ZR z@P?INK1aTm5I4NgpIy=AX<+MY``#_lS;+f9*F9aO_Q*2yolt;ney!JrYQ+vwH&|3~ zGlp+2M{K3%YdJ6ks7V^|)HKf?kAQi;`Md?505Y<6}W=`(ew_A6F zG-Y|xFii^YxRA}PxV2uUyFv)HPx!TOBLxQ2w@MzUyUa!}kKHDTv{>p}8R9~KE5ax# z+et8Oj=#wzDfTP4R0TUifXj#F>!I2Y#~rRT2vYiH2<^C70H(zZeuXJrZ%urCEJRve zKH}|#5P6$ z(f|(l88z~vs+ABBh(uby3@z2RxLd_{o(f(QCeAPc4}Bjb`&btmtP0I~{xqoR=ON|p z8+1VCruEbH)At-;#uZ+fOHVx5SBA8AVr&;Mn5J&YsMv5jbwOQQdMN=nipVJCRL7H! zEBAUwwaipYbKEGJXQn%RxoZ2${bIkWYU?l-j{zw%rlL=T5lg;Rozj|^d?|STyZ=+A zG&~rwpW)qzDkIgG-hURP4zn+{-{iP=2PlE)9q&hlfpb1-y=f>8UeU;<1zxvr->EkW zA1Ror(J1j#C+{t2GJjD2 zV`VmpK=?1U}CTa`V z3H6H_SG5N`fp#h6cU2(qCBPaI(ekc{tqyOfVeEn;cuZsu!2^tmlm=kXmfg(R!YDhy zAz-5GB1Hgl%$99_RgqOxP{5IYpE1yG$5kyC!z>5Qv$q##UtExmRP_Ta-Vd?I{E&k3 zetE~QLxR_#D8CMCAPTirQkw6ysaH%-g8gt2j%B2NAY*9>zH1Oi!;owYJujtU z6bP>o;$BV)JR^Gx&ET#K)@xWEdx`ToAhBKAA$#q|aW*{p^!L-&;NOc{xJVAQsvZ9s zVeRX#+0%cLz}|?ErL$HK`wR5b5XTfEMe-mUF zrvp+fEl55G_z1#}6#4~ZkUh$1z2VK1g8>Tvm9NJ>Kux}Gpyv>nBv#1c6LOJV$Mr}7?xchS+emwIzr%g-#>*zaRsv>?f=lS? zqnk=jCsL%HoED-OD02Q`gPCsX7I7o%<)-7j>iaFpJj-k?4ZEC1hY08pCI&?tBzk~0 zf*rjk)t182s2|n~o8c!Z`ZI_;g#SqQyyw6`0Xn)&_V*$&29jgJv<`p zqPVpW_>wwyT~hXnDT?gI`cf0hdF*-1yOgdYG;D1fT}{20`Vvj{!+3*NY(`>2cco^9 z@5=$vs=c{NyMdX}t>IaTewzw-{BX9Idg#)Qz@BisblCHeBb93HH(&L_9QqcjcfIuo z=m*Z*X``2BzkQnj)PKPR4y>TjdgH-w*Q@SlET^k?`2j5qpH`PsqtDkQ>cH7%fy^o- zuR}*v=cAzkAg9WqvK{af5JL3VI%It#rbMGStWtc6sQNeyv!vsu_qaURHgruL<(h+b zsMyYB&0o{_s&k7Yk%uoke_Cm^f(PmfB)ik0QKt&mAK;{%g=ww{rpY9>cS=KXst%Pi zfc68pr6}!jTBY};O^kNLV6VJxjgr(bP>w~Lv87r))T8{_AU56r=rz^0fA84?3D?yk zUUB(vu9T37+98VUL{CVTGR2ZS&aV2r*)?d_)1ZE$!~tat+u5edc~<~Eo|~?18*8XZ zNaWMq`w1_sc_qeZZZj9ynFAa5BT4PkGg9mf?jDdxz#&AE?rp0k+~|(kuaGH09=d>f z?h?(V6AyfUZWny_s2_0tx|5V3O95qu&F2sSGz)<3mU<5hsVR`Bfdl{dG0=bA$e?ud zZR-?E`(Ht&mRRHewVi25@sDHy4GJ@awE)O;{W~4|ktm|y?i>h(fU=^?rE5i-_w=N`W=&jpT3Z_cKs^5epq|TQ`W%=OQ5`dLRouT8rAkEsv5W zG^UXAGB-DD$Zy6c24-JYvs#p0txQpo4B7t$b206`)jr1A17>^<*=4z|H425K&-SWb zGCf~#Ca!$u7}INV6^KNI~Rk2K+HfUNXImz zLYPQoMv)#0)DE|>a(l0MNbVgN++t}THYN=(>QD)W;7XE0B3N+ee%8iXK9>}dcXT2% z8LgDj2;9Rs=7$+ZsHSyqVcs?H98}@lFLMTRM!0f)wr2uDIOV7VZ(rcKJ=Vq)$2KuL zZo+Q>)>S4M$S3>71`jyF_+NE`8g_cK>DD2=-bSAI`+Tb&lI45oz6Dv*%HtcsCj$ed z!U3cUY057OreFWvRwei}GVdcuIM=;?Tfk{K`Yf**iA#`7`RygNWUAbRxn#bh-?6vA4x}W$g)20>{2E=9|vCL1NmbEQ1@EOaAac z=&MMKJnP(dX?5=hbv3X1%`PN8%QgZ=HGB2UMy*M(lK_c9$6lplajC?lkv+(9*p>vi zTnBUR!14(DPOd2BW>YiM7WpOqcJ=b*>MD(qT1TyCAWM8v92y8ZgPBbqCuP3V>ESH6 zCfCu%-F_n~jPsfigmwE*efc;rstt)rN%EfxXsZoO%3G@Y4xk?hpF=p;*{<#)s5b ztc|8&{HC8R@7$OJ5G9Y7GysJ%hx0}noj+wXa=c=E&3un(E1hvqr*Ep~m2^i{I*p(K zn1vxTtn(oaEp%)XdU04RYgvKpq0=t z_(!gg4aMylFhUuJ9fv6bGa7L9Ly~6AWmN?#7*-viGk_pMXST?%;!>BM)B*zgrQoT{ zRYJMoQ%~Gd5VqUYWbP4hnDTLxqS7KzRx^OO6EFU}g@!sXmb>?uLy$ylpC#=hJMFgZ zF?c}QET`*g^h+JV6fP+Z&7KQ*oUnL&fG25+MFmy!C)tkQt^jubA*&bFU1{5+A`fo> zXQgxC_WfzdD@(gg1RFZf#r3Ka_=@!XpkGP_)mXSRHcQ`1;yQ*FT_C;bwhOGJ$$l|c z=C6Ykl3sC`X3NNw6cwWOEWyJxuqpEb&?eh#4Q)$-v!%t(s4iA!YsXOZW>?XBj(Z*) zgE^!eIULGAWba+>R-D&yQ=jt`ZCV`p*X~9%{DGVXA;YI!-Zq4mZAzQ3Ri)zeT>513;TsOF{zRV%xL4n zE{C=|X(SslBdgS5DN8Gp8k62=%G~Y&LgIFkP_$teE0YcH^^T7WnOQT&D&{15lbZqI zZpz|cKl_TgG>xs1Gt+$%Rfy9armPkg4m=4unTXS4gVGK__4evA#gG+0 z9uk8#2coQ(fkf{oq4bg1OJ{Sv^>@7wDVB^bwwkkxv^nD-s#agN-B+iP6k)BeUO2lV z<2znY2+egMQvT(bm*Z}S+6Si5-n(9Vxk7{H>-dWzMd`6u+jK?z z#j=dhLd~W1vmm|rmkSbQ`H?+I_P??q{Tq_czZ%w*riur3+G%*6{`Plfs=s%zR=6MV z{*Tx2`FzQn`e6`?a_XF~*x%%?t1TRB^6!S5_A1LeSTcbCPWUoJGpE3XHT|y)arOGd zxeDsKzN@VS2|zD^Cp>=o#v93pPt5U$mRH8(xEaehz19Lx^@H|H1nd)GcaEFX3S%gl zD}T^jVvaiCY&i3gn^BDbwnz;fwaHp__<-k3Eo|gW(}6p;2NyQdejj%XrWj1;H3xun<|J+j`K(78@fuz5H;Wn5>m&Ify?xQ zxA{yg?pRrw3Rvg^f8fQa3wg&iwFTpH%j+q>s+&2qAHe;irne062eWZBu)IBv%VH*I zL3V)R$s5@`aaHsZw8=+sAKisj`?F8cMhJd37=t#*vQc&UGt~6LM}B#=l{oR|0I} zk@2Fg~Apu{~_73MY3faj4RTyF;e(4 zEKeQSKt%}x#wa=h%$=`I`5c%pr)nmKN7s$wl$F|1pRgXK;tD)6BjYHb^%;0BUJ;F% zKICN?vX~W!FEb5*<4P@!3{n+Y>usln34UgATqu6}kXN#p9q;I!f>J`1BR6%|hzG#W ztuFzDPEm+)f}dhh(%oerGTZWc0&2j7g3s*e^()VA#e?&G{dvAYqn;{}YgO24LvQ2x~T z?-6{`REE#j$8%4+q(76m_0!dCiQ<1D!AcQmzT2j%?i0(&-CD9l2Y=5k?W!1l;U13g z+u)hf8+@4LH$iAkP1m< zHi75yAIc>E9c2tS-tWOs4|QCYiud2pN__l_ET@IR-2b_e?9U|P-~Ps7;;sf3%31a- z=R#J1b({dDZiaYFNic4k-|DBc>TmfmdJRWmD$a7$_R0bvW2B?9W9OlTH*bTt*lS?^ znr65mK|ehZO~Z<&iP2h@W3s7WVBA2&8taE)C=|MF0D2Jqr+OHvn(;SB_4Kx_IvCL~ zqhAq8{@!*#-P8N^ZL;T3F_*JaAC84-0qi5v=Odu#D3}0tHYF$vQuots2l2UWlVJn4 zL+w@Pavh}#8*iiJxR+ap416b?a6D&Wb)ADwAZV@K&wl>&z?v0Xq9Nr&JyH@;=Rsa*&9jI)T{uh$}-C9c9)zaykVE zb#=_^sGEEM5mUue;yvrR=DQK@=#`%HcVZ)(fiH*@jE;rUahD%S(50SkSH4QqAHVGg zOKTT}B0M@ZC-0I6%P{qjC%?7Y6@!pKp_aK?++yazJDmZhNUgUsCgJ@aWn)>7>_H4d z+UIM$z!l`3wCj3&=7FC?TjdR8YP3r5gGg~kBL*^=R#utMr}PIH6s|L1NjzCBmcM1j zR!t)8tkQBX#mm>epNuKRoq92AxAGXGF2U5>R4bgDnycIg(BI5(|I9X{jDS=e^b-nf z0&xqtar)X#N`{;deNu8AVed7;2jYP8%4lf#yC8op@Iz)BBhns9Fb0KF^E5%8(WZ{O zcwr~O_bu6N3(UoY&JKHAnC@>HVV(J@mxs0jasi7b(&ckX)SVvW(eVb;gzp~PQa9qq z1OdOG3kS6r8*rbg&lEt?64mPgC7hM~8On`%rJBCu_!pyNNLTxAN*>pg06Z}1GsEDf zbz{cg9tT#=lMe>9YQwDf9ORs>wG}+Pk+DUAU))FR79+W168meGhB&p?wRKo6ne2KJ zzv>f8?x3_u#&}>{Fe+8*C$WlSDHz?*1g&nJ*QD%7KnC>KL^fZ=nB`hR}MAJ<-m&} zvphHg4Mlv-_$PXRB7cpJlda`CpBN|L*tx$?E|p;z05(r&x}`7OlYh zL!D0@XzhCnrPJV&f~m!=--w@8b5;Zb@=Z`*EdvTTf*+uM14&L)EHhF7J~w3`Hgpoa zot;<}TUryX@>;+A?bCcN=c242@ErZJJ+}+rwWZe))v9J<2tH%#^f!m)VOQT;wS&I(+B+kBVuk!)&wV z$kXR~*3|32XVb`l&phf64&VsuBs*p}@e~0EQIu^{fD8y20;zI8gP7Wco(uxHI&Y1{ zo6pXh0p!O9K<;8otP5&qgtJ=fjnX5H>#Q4v5`71mja8Ft$n#53-lv(t^@j~+j#Y)R zxjhR#-?Fa*XWV7$;_sP(G9f6=r9~IGTV{B%-JSQJoqsq3`HRp$xoM+a=k|DG)>Ev1 z`Y%C@>t3OzhZxbgV91qed4W~7xYtVg>@1FKlD-dz$D_}~f@LA@^pgQ#JmqmW<|*pV zexW3J{HN3+u=An3n0g?EoRPq(&7~_+M$shKW}c3tr{mX7N{wlhbxDvyb*lI<*(4pv zzT4S+h9!VI*|bd(lcvN9NWU*3*#Y>5J66zQOdSY_Kn6imrtmlTz*cm%du=Ycz==o)2SBLu^CQ8f5q#FR|$2@zr#WhUqfN<1(<9}8xBin<&zC^!%DY!1IW%#P6` zr~R{C@_+AdepOo|7CW>OLGS)T&^4H=Yx2KFPME%dz;aWNA;1Pv43L3SAKdq(kS+?; zD5Y(kPK&DM(O%CZ0(&)KtLi1Kx3IhW{ReqxVMBMI6?k&Bao|L^+iIPdKn~tC!OD3(ZYLmv&uv!H}S#=%i-s6z5rMb9SU3H5w z$?K!VT3TOcrT)@j9JjZjds$V@4CmD=VU_-olP6(yJ%;CER7d<6$ZVletnP8n5XzP$d%^1iIaCUn{HUSxW4G(W#gd=zcD9+u!FvqlM<0<&uc> zX(qMREG0H9oEOa!8hh-4|MOx_T(Kf=*Z?jeV&$=MNb5UOx|E5ff!X6H)^}WI?%hK< zPj|S4ym^tXRV+uu6Hz?#9H%{)SI5bPnYWiz$4QxeAY|K@4!NRUk}P|d z|Gd&lg|X>OIpY>#b%g1RvnTCv?{0zJUV-ihfy@OWB8{=3-nTqvIC1m|tq*ROd+waM z5^gQizF@y8vaN7%o%^jLu1&8tZ15oQEH+mefuGF7_E5+zZ&BMIdoS(&Wte9OzNno@ z`RA+(W2D@>XP*tlBR*NcnuTjqxDE(&_U?^WCSbf*EAm*z_PW%w$2Wqo(MldpQa3l3 z2Io^uk;t*Wm3FTRCC1l?%HTGD@vd@`y(c1y>`LW)qNoR6*DjLU_l3ALsd;XOIeJ!t zIsNrL8H!O$T7 zqI`f4CL!BnD*zm!Cg14xY(nMUUvUVfL%wtnzIo^eXNi z`sVeqsu~P|EW-s%(myh)RE7~MXU(?^6;Ht9)5 zOlyF6pK~_)tfZOc-NdAu5yz#Ok~0rueHTGgE)A~2Mzh?+`+r?CD z-5$bcXXTE92knuNIq0~ke04E%chv$RoJU~|PB%4o05~=k zTkiyb%dS8dq1=a3tnS|0;(f7qm`(p7Z@tB2= zx|}IsZ#aGHyq_0crxLJfQX1I zskymq{HzvVBk(=GOJT9t&*_s1uip+Aru6vv?0ZhKPzU??z&@$nFL9o`?B6^YS@|RN zBaO!?h1P;BT9x;;wgWMiVc2&1HRu^&*DG$O2atXvv>gF! z5lrzo$jOAkUcEXbq{YMzyWfo)hwRq*^M`7ySEml6-Nar%V9B)`4-N_Z^MCo@PF-z& z!+!7HO+k%WW~9D!(9fc}q@PBkhyDClf) zQBfI<&EWWWPD~6H3k%D9U#h}qfNH|(@<~6oE-fwHJtNxG9?llSrdyMy#*91I+eU3K z$Aq*d$;a>}JMrfX3=FJ-I~i8zh;(#B&a%9q%f#Dc z{+|;J=HtG5oT#}q(Lf&6sQ+UzH|&$gr`^gQXFaxeRGT?3zf1rj1sCb%=cZcUnj?{_ knwnAA`p renderSamples(Display display, java.util.List rows, + Map fonts, int sampleWidth, int sampleHeight, boolean advanced) { + Map samples = new HashMap<>(); + for (TextRow row : rows) { + Image sample = new Image(display, sampleWidth, sampleHeight); + GC gc = new GC(sample, row.gcStyle()); + try { + gc.setAdvanced(advanced); + gc.setBackground(new Color(255, 255, 255)); + gc.fillRectangle(sample.getBounds()); + gc.setForeground(new Color(0, 0, 0)); + gc.setFont(fonts.get(row)); + gc.drawText(row.text(), 5, 5, row.drawFlags()); + } finally { + gc.dispose(); + } + samples.put(row, sample); + } + return samples; + } + + @SuppressWarnings("restriction") + public static void main(String[] args) { + // U+FFFE has no glyph in any standard font. Appending it to a string makes + // GC.drawText() lay out that whole string with GDI+ instead of computing + // the glyph positions with GDI, so the rows using it always show what + // GDI+'s own text layout does with the respective text property. + String unsupportedGlyph = String.valueOf((char) 0xFFFE); + + java.util.List rows = new ArrayList<>(); + rows.add(new TextRow("Plain text", "Hello World")); + rows.add(new TextRow("Bold", SWT.BOLD, false, false, "Hello World", SWT.DRAW_TRANSPARENT, SWT.NONE)); + rows.add(new TextRow("Italic", SWT.ITALIC, false, false, "Hello World", SWT.DRAW_TRANSPARENT, SWT.NONE)); + rows.add(new TextRow("Underlined", SWT.NORMAL, true, false, "Hello World", SWT.DRAW_TRANSPARENT, SWT.NONE)); + rows.add(new TextRow("Strikeout", SWT.NORMAL, false, true, "Hello World", SWT.DRAW_TRANSPARENT, SWT.NONE)); + rows.add(new TextRow("Bold + underlined", SWT.BOLD, true, false, "Hello World", SWT.DRAW_TRANSPARENT, + SWT.NONE)); + rows.add(new TextRow("Underlined + unsupported glyph (U+FFFE)", SWT.NORMAL, true, false, + "Hi" + unsupportedGlyph, SWT.DRAW_TRANSPARENT, SWT.NONE)); + rows.add(new TextRow("Mnemonic (accelerator underline)", SWT.NORMAL, false, false, "&File", + SWT.DRAW_MNEMONIC | SWT.DRAW_TRANSPARENT, SWT.NONE)); + rows.add(new TextRow("Tab-separated columns", SWT.NORMAL, false, false, "A\tB\tC", SWT.DRAW_TAB, + SWT.NONE)); + rows.add(new TextRow("Tab-separated columns + unsupported glyph (U+FFFE)", SWT.NORMAL, false, false, + "A\tB\tC" + unsupportedGlyph, SWT.DRAW_TAB, SWT.NONE)); + rows.add(new TextRow("Kerning pair", "AVATAR WAVE To Yes")); + rows.add(new TextRow("Mirrored / RTL", SWT.NORMAL, false, false, "Hello World", SWT.DRAW_TRANSPARENT, + SWT.RIGHT_TO_LEFT)); + rows.add(new TextRow("Arabic", "\u0645\u0631\u062d\u0628\u0627 \u0628\u0627\u0644\u0639\u0627\u0644\u0645")); + rows.add(new TextRow("Hebrew", "\u05e9\u05dc\u05d5\u05dd \u05e2\u05d5\u05dc\u05dd")); + rows.add(new TextRow("CJK (Chinese)", "\u4f60\u597d\u4e16\u754c")); + rows.add(new TextRow("Cyrillic", "\u041f\u0440\u0438\u0432\u0435\u0442 \u043c\u0438\u0440")); + rows.add(new TextRow("Greek", "\u0393\u03b5\u03b9\u03ac \u03c3\u03bf\u03c5 \u039a\u03cc\u03c3\u03bc\u03b5")); + rows.add(new TextRow("Combining diacritics", "e\u0301clat na\u0308\u0131ve")); + + Display display = new Display(); + Shell shell = new Shell(display); + shell.setLayout(new GridLayout()); + shell.setText("Text rendering comparison"); + + Label info = new Label(shell, SWT.WRAP); + info.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + Button advancedCheckbox = new Button(shell, SWT.CHECK | SWT.WRAP); + advancedCheckbox.setText("Use GDI+ (advanced) rendering - GC.setAdvanced(true); " + + "uncheck to compare against plain GDI (GC.setAdvanced(false))"); + advancedCheckbox.setSelection(true); + advancedCheckbox.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + ScrolledComposite scroller = new ScrolledComposite(shell, SWT.V_SCROLL | SWT.BORDER); + scroller.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + scroller.setExpandHorizontal(true); + scroller.setExpandVertical(true); + + int rowHeight = 42; + int labelWidth = 260; + int sampleWidth = 320; + int sampleHeight = rowHeight - 4; + + Canvas canvas = new Canvas(scroller, SWT.NONE); + canvas.setSize(labelWidth + sampleWidth + 20, rows.size() * rowHeight + 10); + scroller.setContent(canvas); + scroller.setMinSize(canvas.getSize()); + + Font systemFont = display.getSystemFont(); + Map fonts = new HashMap<>(); + for (TextRow row : rows) { + FontData fontData = systemFont.getFontData()[0]; + fontData.setStyle(row.fontStyle()); + if (row.underline()) fontData.data.lfUnderline = 1; + if (row.strikeout()) fontData.data.lfStrikeOut = 1; + fonts.put(row, new Font(display, fontData)); + } + + // Mutable holder so the checkbox listeners can swap in a freshly rendered + // set of samples (and dispose the previous ones) whenever a toggle changes. + // Starts out empty; the initial samples are rendered by the refresh below. + AtomicReference> samplesHolder = new AtomicReference<>(Map.of()); + + Runnable refresh = () -> { + boolean advanced = advancedCheckbox.getSelection(); + + Map old = samplesHolder.getAndSet( + renderSamples(display, rows, fonts, sampleWidth, sampleHeight, advanced)); + old.values().forEach(Image::dispose); + + shell.setText("Text rendering comparison (advanced = " + advanced + ")"); + info.setText("GC.setAdvanced(" + advanced + ")" + + "\nToggle the checkbox below to compare plain GDI vs. GDI+ text rendering." + + " See the source comment for what to expect per row."); + shell.layout(true, true); + canvas.redraw(); + }; + + advancedCheckbox.addListener(SWT.Selection, e -> refresh.run()); + refresh.run(); + + canvas.addPaintListener(e -> { + GC gc = e.gc; + int y = 5; + for (TextRow row : rows) { + gc.drawText(row.label(), 5, y + (rowHeight - 4) / 4, SWT.DRAW_TRANSPARENT); + gc.drawImage(samplesHolder.get().get(row), labelWidth, y); + y += rowHeight; + } + }); + + canvas.addDisposeListener(e -> { + samplesHolder.get().values().forEach(Image::dispose); + fonts.values().forEach(Font::dispose); + }); + + shell.setSize(700, 500); + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + display.dispose(); + } +} From 08936c83d662f6defa4d10b6c0eb4e5d915f8fe4 Mon Sep 17 00:00:00 2001 From: Heiko Klare Date: Sat, 15 Aug 2026 13:10:55 +0200 Subject: [PATCH 2/2] [Win32] Disable obsolete fallback for drawing text without GDI+ A check in GC.drawText() makes the implementation fall back to the text rendering based on glyphs and their positions calculated by GDI even when GDI+ is used in all cases except when it contains specific characters that GDI cannot handle. This was necessary more than a decade ago because specific Chinese characters were not properly rendered by GDI+. But this is quite non-intuitive as in case GDI+/advance mode is enabled the consumer will usually expected GDI+ to be used for rendering. In addition, the problematic scenario from back then works fine now. This change thus adapts the GC.drawText() implementation to use plain GDI+ whenever it is enabled. The fallback code is preserved but only executed if a newly introduced system property is enabled. This allows to switch back to previous behavior in case unexpected regressions are found. The property is to be removed in a future release in case no regressions are found. It is evaluated once per GC rather than per drawing operation, so that reading it does not add cost to text drawing, while a newly created GC still picks up a value changed at runtime. Rename useGDIP() to useGdipTextLayout(), since both of its outcomes draw with GDI+ and it only decides which engine performs the layout. Extend GCWin32Tests with additional regression tests covering not only the previously fixed underline/strikeout invisibility issue, but also style-decoration combinations, mnemonic underlining, mirrored/RTL text, complex scripts and charsets (Arabic, Hebrew, CJK, Cyrillic, Greek, combining diacritics) and kerning-sensitive text width. The tests assert the correctness of the GDI+ rendering itself and, where a reference value is required, use plain (non-advanced) GDI rendering of the same text as baseline, so that they remain meaningful once the system property is removed again. The fallback itself is deliberately left untested, as it is meant to be removed once the new behavior has proven itself. Extend Snippet395 with a second checkbox toggling that system property at runtime, so that the default and the legacy text rendering path can be visually compared while GDI+ is active. Fixes https://github.com/eclipse-platform/eclipse.platform.swt/issues/3091 Assisted-by: Claude Opus 5 --- .../eclipse/swt/graphics/GCWin32Tests.java | 291 ++++++++++++++++-- .../win32/org/eclipse/swt/graphics/GC.java | 35 ++- .../previews/Snippet395.png | Bin 38049 -> 49119 bytes .../org/eclipse/swt/snippets/Snippet395.java | 48 ++- 4 files changed, 338 insertions(+), 36 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/graphics/GCWin32Tests.java b/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/graphics/GCWin32Tests.java index d6af2d2c10b..f6a76fd3d09 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/graphics/GCWin32Tests.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/graphics/GCWin32Tests.java @@ -69,6 +69,29 @@ public void drawnElementsShouldScaleUpToTheRightZoomLevel() { assertEquals("Drawn elements should scale to the right value", gc.getGCData().lineWidth, gc.getLineWidth() * scalingFactor, 0); } + /** + * Regression test for + * https://github.com/eclipse-platform/eclipse.platform.swt/issues/3091: an + * advanced GC using a font with an underline (or strikeout) decoration drew + * no ink at all, i.e. the text was lost entirely rather than merely losing + * its decoration. + */ + @Test + public void drawTextWithUnderlinedFontRendersVisibleInk() { + Display display = Display.getDefault(); + FontData underlinedFontData = display.getSystemFont().getFontData()[0]; + underlinedFontData.data.lfUnderline = 1; + Font font = new Font(display, underlinedFontData); + Image image = new Image(display, 100, 100); + try { + assertTrue(renderTextAndCountNonWhitePixels(image, font, "Hello World") > 0, + "an advanced GC must draw visible ink for text in an underlined font"); + } finally { + image.dispose(); + font.dispose(); + } + } + /** * Verifies that underline and strikeout styles requested via a font's * {@link FontData} are preserved when GDI+ cannot find the font family and @@ -123,35 +146,21 @@ public void fallbackFontPreservesUnderlineAndStrikeout() { } private static int renderTextAndCountNonWhitePixels(Image target, Font font, String text) { - GC testGC = new GC(target); - try { - testGC.setAdvanced(true); // required so font style flags (underline, strikeout) are applied during rendering - testGC.setBackground(new Color(255, 255, 255)); - testGC.fillRectangle(target.getBounds()); - testGC.setForeground(new Color(0, 0, 0)); - testGC.setFont(font); - testGC.drawText(text, 5, 5); - } finally { - testGC.dispose(); - } - ImageData imageData = target.getImageData(DPIUtil.getDeviceZoom()); - int count = 0; - for (int y = 0; y < imageData.height; y++) { - for (int x = 0; x < imageData.width; x++) { - RGB rgb = imageData.palette.getRGB(imageData.getPixel(x, y)); - if (rgb.red != 255 || rgb.green != 255 || rgb.blue != 255) { - count++; - } - } - } - return count; + // advanced mode is required so that font style flags (underline, + // strikeout) are applied during rendering + return renderTextAndCountNonWhitePixels(target, font, text, SWT.DRAW_DELIMITER | SWT.DRAW_TAB, SWT.NONE, true); } /** * U+FFFE is a Unicode non-character that no standard font has a glyph for. * Appending it to a string makes an advanced GC lay that string out with - * GDI+ instead of letting GDI compute the glyph positions, which is the only - * way to exercise the GDI+ tab stop handling. + * GDI+ instead of letting GDI compute the glyph positions. + *

+ * Since GDI+ text layout became the default for advanced GCs, this is no + * longer strictly required. It is kept deliberately so that the tab stop + * tests exercise the GDI+ layout path irrespective of the state of the + * {@code useGDITextRenderingWithGDIP} system property, which exists to + * switch back to GDI-computed glyph positions. */ private static final String UNSUPPORTED_GLYPH = String.valueOf((char) 0xFFFE); @@ -389,4 +398,238 @@ private static Stream zoomAndHeightArguments() { return Arrays.stream(zooms).boxed() .flatMap(zoom -> Arrays.stream(heights).mapToObj(height -> Arguments.of(zoom, height))); } + + /** + * Verifies that an advanced GC applies a font's underline and strikeout + * decoration for every combination of weight and slant, not just for the + * plain, non-bold, non-italic case. Decorated text must produce more ink + * than the same text in the same weight and slant without decoration. + */ + @ParameterizedTest(name = "{3}") + @MethodSource("styleDecorationCombinations") + public void drawTextRendersFontDecorationForStyleCombinations(int styleBits, boolean underline, + boolean strikeout, String description) { + Display display = Display.getDefault(); + FontData decoratedFontData = display.getSystemFont().getFontData()[0]; + decoratedFontData.setStyle(styleBits); + if (underline) decoratedFontData.data.lfUnderline = 1; + if (strikeout) decoratedFontData.data.lfStrikeOut = 1; + Font decoratedFont = new Font(display, decoratedFontData); + FontData plainFontData = display.getSystemFont().getFontData()[0]; + plainFontData.setStyle(styleBits); + Font plainFont = new Font(display, plainFontData); + Image image = new Image(display, 150, 100); + try { + int pixelsWithDecoration = renderTextAndCountNonWhitePixels(image, decoratedFont, "Hello"); + int pixelsWithoutDecoration = renderTextAndCountNonWhitePixels(image, plainFont, "Hello"); + + assertTrue(pixelsWithDecoration > pixelsWithoutDecoration, + "Text decorated with " + description + " must produce more ink than the undecorated text " + + "(decorated: " + pixelsWithDecoration + ", undecorated: " + pixelsWithoutDecoration + ")"); + } finally { + decoratedFont.dispose(); + plainFont.dispose(); + image.dispose(); + } + } + + private static Stream styleDecorationCombinations() { + return Stream.of( + Arguments.of(SWT.NORMAL, true, false, "normal weight + underline"), + Arguments.of(SWT.BOLD, true, false, "bold + underline"), + Arguments.of(SWT.ITALIC, false, true, "italic + strikeout"), + Arguments.of(SWT.BOLD | SWT.ITALIC, true, true, "bold + italic + underline + strikeout") + ); + } + + /** + * Verifies that an advanced GC underlines the mnemonic (accelerator) + * character requested via {@link SWT#DRAW_MNEMONIC}, which must produce + * visibly more ink than the same text without a mnemonic. + */ + @Test + public void drawTextMnemonicUnderlineAddsVisibleInk() { + Display display = Display.getDefault(); + Font font = display.getSystemFont(); + Image image = new Image(display, 150, 60); + try { + int pixelsWithMnemonic = renderTextAndCountNonWhitePixels(image, font, "&File", + SWT.DRAW_MNEMONIC | SWT.DRAW_TRANSPARENT, SWT.NONE, true); + int pixelsWithoutMnemonic = renderTextAndCountNonWhitePixels(image, font, "File", + SWT.DRAW_TRANSPARENT, SWT.NONE, true); + + assertTrue(pixelsWithMnemonic > pixelsWithoutMnemonic, + "Mnemonic underline should add visible ink (with mnemonic: " + pixelsWithMnemonic + + ", without: " + pixelsWithoutMnemonic + ")"); + } finally { + image.dispose(); + } + } + + /** + * Verifies that mirrored ({@link SWT#RIGHT_TO_LEFT}) text drawn by an + * advanced GC covers about the same area as the same mirrored text drawn by + * a plain, non-advanced GC, which serves as the reference. + */ + @Test + public void drawTextMirroredStyleRendersInkAreaComparableToGdi() { + Display display = Display.getDefault(); + Font font = display.getSystemFont(); + Image image = new Image(display, 200, 60); + try { + Rectangle gdipInkBounds = renderTextAndGetInkBounds(image, font, "Hello World", + SWT.DRAW_TRANSPARENT, SWT.RIGHT_TO_LEFT, true); + Rectangle gdiInkBounds = renderTextAndGetInkBounds(image, font, "Hello World", + SWT.DRAW_TRANSPARENT, SWT.RIGHT_TO_LEFT, false); + + assertAll( + () -> assertNotNull(gdipInkBounds, "GDI+ mirrored rendering must draw visible text"), + () -> assertNotNull(gdiInkBounds, "GDI mirrored rendering must draw visible text") + ); + // Widths may legitimately differ a bit (different layout engines), but a + // gross regression (e.g. text collapsed to a sliver, or drawn far wider + // because mirroring was applied twice) would fall well outside this range. + assertWithinTolerance("mirrored text ink width", gdipInkBounds.width, gdiInkBounds.width, 0.4); + } finally { + image.dispose(); + } + } + + private static Stream complexScriptsAndCharsets() { + return Stream.of( + Arguments.of("Arabic", "\u0645\u0631\u062d\u0628\u0627"), + Arguments.of("Hebrew", "\u05e9\u05dc\u05d5\u05dd"), + Arguments.of("CJK (Chinese)", "\u4f60\u597d\u4e16\u754c"), + Arguments.of("Cyrillic", "\u041f\u0440\u0438\u0432\u0435\u0442"), + Arguments.of("Greek", "\u0393\u03b5\u03b9\u03ac \u03c3\u03bf\u03c5"), + Arguments.of("Combining diacritics", "e\u0301clat") + ); + } + + /** + * Verifies that an advanced GC renders visible ink for text in a variety of + * scripts and charsets. This is a smoke test only: exact glyph shaping and + * positioning is left to the text layout engine, but text must never be + * silently dropped. + */ + @ParameterizedTest(name = "{0}") + @MethodSource("complexScriptsAndCharsets") + public void drawTextComplexScriptsAndCharsetsRenderVisibleInk(String description, String text) { + Display display = Display.getDefault(); + Font font = display.getSystemFont(); + Image image = new Image(display, 200, 60); + try { + int renderedPixels = renderTextAndCountNonWhitePixels(image, font, text); + + assertTrue(renderedPixels > 0, "GDI+ rendering must draw visible ink for " + description); + } finally { + image.dispose(); + } + } + + /** + * Verifies that a kerning-sensitive string drawn by an advanced GC comes + * out about as wide as the same string drawn by a plain, non-advanced GC, + * which serves as the reference. Minor differences in advances and kerning + * are expected, whereas glyphs collapsing onto each other or a roughly + * doubled width would indicate a real layout defect. + */ + @Test + public void drawTextKerningSensitiveTextWidthIsComparableToGdi() { + Display display = Display.getDefault(); + Font font = display.getSystemFont(); + Image image = new Image(display, 300, 60); + String kerningSensitiveText = "AVATAR WAVE To Yes"; + try { + Rectangle gdipInkBounds = renderTextAndGetInkBounds(image, font, kerningSensitiveText, + SWT.DRAW_TRANSPARENT, SWT.NONE, true); + Rectangle gdiInkBounds = renderTextAndGetInkBounds(image, font, kerningSensitiveText, + SWT.DRAW_TRANSPARENT, SWT.NONE, false); + + assertAll( + () -> assertNotNull(gdipInkBounds, "GDI+ rendering must draw visible text"), + () -> assertNotNull(gdiInkBounds, "GDI rendering must draw visible text") + ); + assertWithinTolerance("kerning-sensitive text ink width", gdipInkBounds.width, gdiInkBounds.width, 0.3); + } finally { + image.dispose(); + } + } + + /** + * Asserts that {@code actual} is within {@code (1 +/- tolerance)} times + * {@code expected}, i.e. flags gross deviations (roughly halved/doubled or + * worse) while tolerating the minor differences that are expected between + * the text layout of an advanced and a non-advanced GC. + */ + private static void assertWithinTolerance(String description, int actual, int expected, double tolerance) { + int lowerBound = (int) Math.floor(expected * (1 - tolerance)); + int upperBound = (int) Math.ceil(expected * (1 + tolerance)); + assertTrue(actual >= lowerBound && actual <= upperBound, + "Expected " + description + " (" + actual + ") to be within " + (int) (tolerance * 100) + + "% of the reference value (" + expected + "), i.e. in [" + lowerBound + ", " + upperBound + "]"); + } + + private static int renderTextAndCountNonWhitePixels(Image target, Font font, String text, int drawFlags, + int gcStyle, boolean advanced) { + renderText(target, font, text, drawFlags, gcStyle, advanced); + return countNonWhitePixels(target); + } + + private static Rectangle renderTextAndGetInkBounds(Image target, Font font, String text, int drawFlags, + int gcStyle, boolean advanced) { + renderText(target, font, text, drawFlags, gcStyle, advanced); + return inkBounds(target); + } + + private static void renderText(Image target, Font font, String text, int drawFlags, int gcStyle, + boolean advanced) { + GC testGC = new GC(target, gcStyle); + try { + testGC.setAdvanced(advanced); + testGC.setBackground(new Color(255, 255, 255)); + testGC.fillRectangle(target.getBounds()); + testGC.setForeground(new Color(0, 0, 0)); + testGC.setFont(font); + testGC.drawText(text, 5, 5, drawFlags); + } finally { + testGC.dispose(); + } + } + + private static int countNonWhitePixels(Image target) { + ImageData imageData = target.getImageData(DPIUtil.getDeviceZoom()); + int count = 0; + for (int y = 0; y < imageData.height; y++) { + for (int x = 0; x < imageData.width; x++) { + RGB rgb = imageData.palette.getRGB(imageData.getPixel(x, y)); + if (rgb.red != 255 || rgb.green != 255 || rgb.blue != 255) { + count++; + } + } + } + return count; + } + + /** + * Returns the bounding box of all non-white pixels in the given image, or + * {@code null} if the image is entirely white (i.e. nothing was drawn). + */ + private static Rectangle inkBounds(Image target) { + ImageData imageData = target.getImageData(DPIUtil.getDeviceZoom()); + int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE, maxX = -1, maxY = -1; + for (int y = 0; y < imageData.height; y++) { + for (int x = 0; x < imageData.width; x++) { + RGB rgb = imageData.palette.getRGB(imageData.getPixel(x, y)); + if (rgb.red != 255 || rgb.green != 255 || rgb.blue != 255) { + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + } + if (maxX < 0) return null; + return new Rectangle(minX, minY, maxX - minX + 1, maxY - minY + 1); + } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java index cb4246c32d8..45414f64354 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java @@ -110,6 +110,24 @@ public final class GC extends Resource { static final float[] LINE_DASHDOT_ZERO = new float[]{9, 6, 3, 6}; static final float[] LINE_DASHDOTDOT_ZERO = new float[]{9, 3, 3, 3, 3, 3}; + private static final String USE_GDI_TEXT_RENDERING_WITH_GDIP = "org.eclipse.swt.internal.win32.useGDITextRenderingWithGDIP"; + + /** + * Whether text is laid out by GDI and only drawn by GDI+, instead of being + * laid out by GDI+ itself, which restores the behavior that was in place + * before GDI+ text layout became the default. + * + * This is only a safety net for unexpected text rendering regressions, so + * that consumers can fall back to the previous behavior instead of having + * to downgrade SWT. It may be removed at any point in time and must not be + * relied upon. + * + * Evaluated once per GC rather than per drawing operation, so that reading + * the system property does not add cost to text drawing, while a newly + * created GC still picks up a value changed at runtime. + */ + private final boolean useGdiTextLayoutWithGdip = Boolean.getBoolean(USE_GDI_TEXT_RENDERING_WITH_GDIP); + /** * Prevents uninitialized instances from being created outside the package. */ @@ -2854,7 +2872,20 @@ private void drawTextInPixels (String string, int x, int y, int flags) { OS.SetBkMode(handle, oldBkMode); } -private boolean useGDIP (long hdc, char[] buffer) { +/** + * Decides whether GDI+ lays out the text itself (Graphics_DrawString) or + * whether the glyphs and their positions are computed by GDI and only drawn + * by GDI+ (Graphics_DrawDriverString). Note that both cases draw with GDI+, + * so this only selects which engine performs the layout. + * + * Unless the legacy GDI text layout is requested, GDI+ always lays out the + * text itself and the glyph inspection below is not reached. Both are to be + * removed together with the fallback. + */ +private boolean useGdipTextLayout(long hdc, char[] buffer) { + if (!useGdiTextLayoutWithGdip) { + return true; + } short[] glyphs = new short[buffer.length]; OS.GetGlyphIndices(hdc, buffer, buffer.length, glyphs, OS.GGI_MARK_NONEXISTING_GLYPHS); for (int i = 0; i < glyphs.length; i++) { @@ -2882,7 +2913,7 @@ void drawText(long gdipGraphics, String string, int x, int y, int flags, Point s if (hFont != 0) oldFont = OS.SelectObject(hdc, hFont); TEXTMETRIC lptm = new TEXTMETRIC(); OS.GetTextMetrics(hdc, lptm); - boolean gdip = useGDIP(hdc, chars); + boolean gdip = useGdipTextLayout(hdc, chars); if (hFont != 0) OS.SelectObject(hdc, oldFont); Gdip.Graphics_ReleaseHDC(gdipGraphics, hdc); if (gdip) { diff --git a/examples/org.eclipse.swt.snippets/previews/Snippet395.png b/examples/org.eclipse.swt.snippets/previews/Snippet395.png index b802778b031b7cc1f2ec63d3a34ec2a616d36979..3dc24d77a77ce4fa5c56a7731e4145f27c83ddee 100644 GIT binary patch literal 49119 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

Htl=zC9k)AWB5;(Ms;9@%Nc zf)@{FQY~)G7p6~fyO#Q!hOj$bqrpn9P1tItY*y;!rP>TU-RE}fDi7Z(nP1zva7Ouu zIFDyiQJq$G9^p*dq;V+N9ba%%)nCxIh{zi%b*A}INa%OKqk z;kr|g1SX0kgYi?*jo3ZzAzO*xcb!&P9dmyZEchLx!)N*4OLz-8cb!^^J!M@Mz(d@9 zh5Z^YP_@J&XKKLMo+$CF)2H zp4;w=>#4aLPQ$kKxGY?Nw!kK#qr*OVG3>L(U6en$N_4g)cv6rgWPJY`E+R1Lw5xj% zusNZU3Qu(XEas8l@DQ#i3`qrz%gpu2{R;oOI_^fkij^HVEiv!?LGSUE&3jF`9=op| zSLH2nIIg`0Do=pDufmV8cLXfxPgV-_83CJM=KR0a!qoxIp8he*qQ2jOKjN0}8v)y^ z9_#0B7u@0~LOiP*bzE~&D`Vx%Si0EiU!9}e%Brr{LJh-1NCi88%ekusUMLgu5$MdPH^dD4DnpS6o|& zuxhAm!8gnlG8QHazEdJoS1m6Pba{_!F9M3deL1(Kx@Kve_m|wlNJL5=FQ2VhZhfJ^ zL&9px<*qGr{dMtO2lI5ffX>nEIcJ(W_#<}_s0p=-Uop_B5EzI3B>}@kLVRqtoEy_w zf4pEEAC*fosE73&&+7#_mw>APSoZMjn( z%?s-iTAl?%BPzn%(kh?he(Lx{m^S@YJ{?K+{Ak3HwzL$HuKM0FMy#2Mu3y9B@v%Y3NZ|DtK)s8m zK1dD@1!%0o6H4uIy3rcaN;`;9XO$Qqgdc$AojHfE&SNSi3wh47AxWZ}-(&7s7VBS^l%bbFNcm-rz<(p|{!01Vx0h_LkY3wod7mS@1g?Y(FR zlde^FD_HM!DvG8HGEp66xX#|@hO*uhG|KWEa#dR^$j7d-hWo#9tZz}lgJZzuzw^D& z1Eu|G0Hq~>lorryUA~iRyRW8^A8DJj(f%eF*CH|Q1;j1NDD8T>F(Dq4J?q6(n`+B| zmTedoi_eX~!%}@fzTtz$KghF+^;J!nw=NE0*#_3yGUIg-u*W`3-KS4eMlBO}GsUQ} zM5(d}c)zv(CE(N525?|rd_KS*U2ny(;$j^7p5t43*pKx88p_#K4Mm|x6^iwe#OBK? z2aITRYiamATDA9JZgV|~dO9+aD`1U*0NQJp2l{K}eSfme8WrCKFmG+|hszrD%1@hE z%$PHsoNJW3j3fmZ$W2S6$#j~-gmK*fU>x1Y2%7G@qk}7J2fYM&lu*ohbisFHxW)L* z_h>hV!7LU=-O<4=sGR5ckW5Vod)5TPng)CQNbgswC>f+Z>@J?(_u^7rE086vJR7O_ zOwcC-)tm?u{de;PUzo}ttASl9*w1Ppmt-w`jfsUXV`*2RRrDy&&u`?^hL-Lu!r<+Z zzr2l8ff4^WBSs2;)vIgqn3urxf_4p$+Gm9E`Ig4G3CX>=VRLbpP#kFNvm zVN;ERbY<&DXp!KvHZRVJq^!kMLBR|HwzJPL@JbkLw=232Z$vL#jCMgRs38bO(_cBqU z>dNW|gbSA`vT(*4@dmEkzhw<(asgBDuIwynPW*MC>U1%QTBNdB#rZa4-X1?X zOKk(ZLP9!TAe?qOeSW1zh>*5k%pfp8FjLKBVq>2Yi4BQakC0@7y@&*`b&{@tuNFW!3|MlF5t%I&dUuwxZ7{FU0ieJk#Iv6~+ zz63Tler&)c@kAW8>V{m)HKT5Jt1Dk5eoExBYHLOARTy^t%gGX#tB$?EOib7?9%~3` z*uS9I_`-(pCGo#l&cBeJzk+JEL#0&);d}3^pr$!Rz~u{pycf44JahfhNlFODLatvj z)Y7f<30yQM)$}R+6iGP=G-c`V%boM(7DHu?aT%dh7SMjdk!N*{Caa<#PTjXVW=JhG zB$nn_5^}+CF~@W!4b((Jhr8w6d;$Fh&$FLrxSrO1}6%a-dQC;08!T}?~|%xUn=X*x|@Oo3FOu+0uSrEA|Y zuCj{JLc9dKkz0})?u@JBk(E9nIChb-+cB>9R8)Hm4AEQ^RAxad;v^BXu()H}=4uXs zB%9JUK9bw}W|1DV7B@9RJCw3x$v26?HKx~%d?g%57v1WG&r>}DZ5#>NUHdw5)H}XY zjEBh+H4LmT?Fh%dQfD*0Ol`byMqL&AbgVwTavwgg_)a+R`zZ}oBaU*Rt&D^~koGKp zJIm&Kg)`)fN~|w@epagRKrA*pKPC(J6j0)TO1u^9EVRZf&!R*d7o{ZrNRE+al#=uH ztxM9+t%(gCN%R~~(NDLxvheNWV1)(}SW_NP*kkmn0!H`E+?g32MBc=`2#~l!pZErS z{ibC?#(>6hbTD%$T@zFzsLT`b*WyakdWH6*@SqzHPK*&c`NaHvq{;~0Yo51RCuu-L z$V<^mPjGTp7S#G=F*)l>uBym*Yx>+N@_FQ`!fa=;f;vZojjNb%sW$tkJnm+3l%%I2)-^f{*K zi#n=qWKTJOo!_L>M2*O4CKA@41R792*dW&#``Z&}Imv6l_!Yf`P(S|mNP0c?;><0d zyUA1U*bGLO<6XIVHF=b^ml}+FQjBA8wtYe&dKeS4 zuZ{MDg;}U#KPvW6oqF*vd*1syQ^!){1w-`msZC*aW5%;lwuvou!S&$%`PO`19qZ4J zK^m%jgD$8qo6j}S!K9V#<+pD+`oms|WqP9Kt;YFTq5P`MOzE60D=dUtpW4LOFX#g^ zyf=#wVJ9k5J#q7u0Nhx^EHdoQ4S*y<%n02Hi-i1FD?nfW-^ptNs;4_gy3|c z4CylIS-wYIze;Udb#B=+`S(GwTriR=E(o%qxVX4zdI_>{W{m6@Iru%!6{~kk-~FR* zn%H)P*zo5cf@Gn8qU8A3arOV@RiG_gs-B+Q3ZA^zul9WT1WC<-mWanzk1k%NMPTS{0T*JjLb#JL`W!Vz9oDQ(2(V}YDbEvuXrsHJ zyzaeO0V&LbIW5I7bdFcCOKDdNrV8M*3l!qwD|2|Hpt(_Y#@~Ej&M4}Bn4F=&$xl7FGa4l53)`5ref;x%~_a?Pz-Vurt8?^0Q^106n?}~g2`O%x4?Ah zsOaulQ=!?2>;a~GBI>nV9fJK7`Mybi{n#2f~Y)I6~J8) zYh^d)#%_c{jLQ?3OHRBx)tMMkTCWnAv>f3ikqZTh;YRkd>mq6V@|c%rimv+h8pr0n zoH7eIzo^FeMq@fE><-A!MIoP?ZX6_R%w;U~;UEjTo-yB(b@Rsxb&kEr<5ZQ36RK;! z_`IWys_k3bgz2Xxn|p4zEf-uVvD`v>v9=ro-im~%lPS=tTbmr^fQyVow zj;*0kc~3X5@-#r9#c=a+rBZj46HE+4WmQ4MV#!7R0b3z8gnhAqL7ZDST8a;^Hg249qVJuUQu!n~84l#6Yt0)8t{Lfo5aTMV?m%;ps(BQ?u5lDxXoz!3L3t3n2ah{H z<@s#RYtRhdZ^sTD)#G}q35o+!@O?C2J*DYZ&Rhq~1rg5@$M*K;3Xbn{pDUnGRAKvI ziy-R?d-d#l7g&3=D#2!lrgvZ<3OX;h&%_i|dWUlFR#1CAQr`waiMI{Q_-B@)J>QxSp# zce*ZHzvEGLMg^)f@blXrinagzp*3LuYJ1XlhgpXc`NZ!169wMtWb~rkl!Q$W{XQ}} z%Cp{8EnTzmy7I~74yOFal(WB^Nj9SkIg?jgJ1%?NhxYf~8_B)`NBhKk>L1JT{%x3k z*#OE(I`sFrw}PIklARv}iK%R;F%QNMsaHp^z5%0eN>#${`d)^YX^J8L}I-5{tXukm_xNg5Is&oZC z)tAl(>xrVeo_rpf%QvuDGk6J9yukGGw!&M+QDVP^WY2RvhnQdZXYF+FaIzFs7+YS8 zlipny?e3UwjD^+NAzsm(K-nFtzcf4xt~A7t2$|{|OOpj6B`8|czNTH;I6P+M4t&%& zHwXpy7$$=kXA;V$ty7zlav-hwb+6vt({W4X;}Uk)$+)c8(0Zr6%6?9+cH6@MRtZ;c z>lLc^{{lk3W_tkT8%~79j(J{3V3+@yXmFYuwa>F9(1=TDu12s#o)ZLGV8~F&(qvr! z*s2~neg&k8vPHqA*<+eLcB6e-PqZM?R_W} z{z}{)m*2Heu%W1WJVaXI@vTnwdY-(AurAtS6mQ+ATH;)4H8}Fg zDVN>Lbrfw*2mQrILBF6MUXDI<7uh0NlVsH!msReV)*`t1O3G8S+8$a{cgsPnl=K~0 z$08~R)ortu!^cl3B99Y8XCrAL{09bn9XU2H)gDP=y+GQ_nPYF~DR>|5ED+c~WYe|%9fz<<~=kERn0e0UkT82fAfhGI$QH}ynm6%bVk7cps z>?H`jMlu*!sUf3{O^7b^_|_m1jU$%^E|3RIz6=$2I5g3i~-a+e$uJ9JHLbaW@wENTS!8_^05VhN>)FoLUMMd_1f?FB-Gn(;MZ zO~wLldi-?Z-MqXB#mNSv&EWdp{vP`UU$(gl=i%n}H1*^hE*={A@_P%1E;QB2GJK?3 z>wGNhbU6}n37~Qo#jCmB&Y4L&CK+eorC)oojMGD00*kOVO&Uxe5w-_7#?2iNIsa6d z9`|9AYAtFnb3I%3P_J%b!D6_igWG`*TokQ?h^DUVhG$#gC$Wu6s@QrjHHMoY<&|NUxS?i#~Ow>3d zcV&Wz>iK?&+tx}-<(URj^dB1H-ie9)SeFSkLf8EWgtR*HN8N;?74net4&f^yKV$HV ze;Ja${=0@5Z0J7>$=2TACB0R>@Mw+Be;b3B>kmc$C+g0BFjW#)nlYCu$x~~ZCQpx6 z;wtI_aW|k$ar4lQB4CtzVZ;zro56%QY|T0Ox%fFfa7%*{w=kG?fxfR&OY%&ivl^FU zU$9y${E*O?&JQ+fgTp&?9i%H{!FYG>a!byF;?u?XH{9F|ow|7$cRLdM6~zc8W_-$z z0GiVFG_~}e_Hb8`oW1g^jB>I*X;%n$>3?I-|B>R-uNME9PbXLARJA4FBA7Kg0`tg6 zKDXAE1dulBN4x}`eCnz8k79%hjtNTOAX@I|VFU6_ ziZmae%8oN&jIc`^PH2ADv^*H4py&#DXgnLox^>$?RK0S}pa4|vf_%Aixm-CR-o-Od zWhL)TKDEXN#DXB?VWkMz0U4^={sQIfG-bBD^xpNd`zh|KyAFgMK_+Pkd7OS3hbVN zYP~uo_FAh0l&$5BW8EVaSBw)4o#JHW@CeOY|AM0%m7e;lE=^CYiu%>CqyD`7b~Y$V z$r9ey-u7B6?b~4dSY4G3a0{JU;vfC`y3B@utmef+gMu1A)QRgBAlP!@$iP-fcA1&|I)RGB835eidLkZ%Rcus&~9 zYjWd9GO8pUpupi^P=-DQp|dFy&YNG%X_-}O?<{LWf2@K;2wdd=@y+DR>I zgl+au`>!A3aiK(SZ07l$D{bDP8|_0=z`Qc5UEYHw@C&CWZ)I5HbF4N4!b6OJ_~=g3+sD{e@6J9yxlRJ^&(?wt4uq zfAy>ZvMr}+hgg7%j1GbT0FQ^gfIu~PxR}N@VPjwgfb_}~FIogBh*I?FpCL?AH$>r1=D%&ftZt;&*JS|jN~Y)NzPgF=oX%j`2? ze11z6dG`Lv87B{o#f;j#Jh|$SZZt)K9B%gP+=EI4p?3!n)~wV}D<0FU$3^wrFwdZl zk#?e_A<`pxyO?{-B(rvs?}WQ89#g8a8DNS?TiL)t{N6*N zS6q&(zlBX9+zd!tk16VDKO$V<`73{HchubOb}jWfd`TO#e*gxZXf0}yUcS#=vgBq3 zW}Pq@xVu-!rhz(|%R=&t42KWAaoy|8U%De=V&c0Sxln4LF^V+1P5 zQk$3!kX{x9l4XifEajE5yu}Z6`|?@n_^t6VMes1F#zj$|TuuAmyF3tH}dl!AATh+Kn@I5zYKDZNueB5#41LG@==WDN80^i${Xc=g{{E+aU?LCw{!)MgOyL34)|M{rB>9 zB24c83iwa}O)wV;B(5;|3uupN;g~osScM!Y{iyWq7~BXk2Ru!}UU5i|0^vGtw+J;A zWg5v5nap_#;H8FvKfu|cuKx{SwYU=_twl3>g(=G1ZTEU!B+<~*g&PksxLK!{$E1my z(fHB50D9Vm!7zq#O>|t^Zuv}F-7%7d7;YDt%|&jK?8D@;V1qj6YoT;y2YK|5%XmFY zk>mMOaa_?SAcYZSS9PEC9fNDJ9ffI+$9yW+{9m&>`))~*OP_+ji6{198v6eea$S2y zJ5;&DHYZ-GTWM5&{EUuCRyendN6gKYcM&|{Z4tGdVdLY5-xUXj*4er&oU1q|pJp8< z3zCv$DFD*VO)aYH4ay@(ahnw1zVywGvpjDB;N3&-&$68>L1icmCJsWw>{Qr5bwMmFOU z?rFrResbaG&h`HH0l@E%xY#sh3oSF!v?x}!<8hXfZ5dgM<)F5>GS|h&X=}(uGf>g` z4eK}6(v#^om48DCjTZv&11Kc6#5WIXk*lW+l97c*QX@{ zNn__&YBqmAt$&E16ZJ4>J6i>ws`paiuAw5J5M4e{CV)L8a>CHdmyXV2eB|p6jilDGEop9B7HK@-)IX6-U{Tty0 zGQ;0i&v0ae{8`ihNH*~EZ$u5hVDrCEXo&8nLcp1IJS2!1#QR3RD;=eP{X-8)@kut_4%SG>x8(`I{sM2J1Q%~U96o71U&;sD=UZA8wL@Tuyfbk zw>L_80o0vISg;VXa?+BcV(7tFCbiq-PMkJu_qpRL+a?~rj&Qq~G_dxtNw@F)3BeLD zk4@E;Jcq==bMEq4LW}q8AUMyHw2PK=Mv10Rz>$_9fEzt%Jk{g-Raakn!@~VT8YmQM z6;iRpGroDC*N4(Qs`QYPm=OdZ->Y%}7~o6YIgQWn7J^ihl`#pknboEMqPI$T&bOF0 z1{w=qYy^H~7dCxaHBk^~06I9|b!6@vwQCMMYZ75#RMkIaw!KL17aa>TTFyo4rRN*J z{-}(ylu8}vfS!3h@jnieoYAAK@D?A0=0ff>0+R6VcyG==9|5@p&c=_&-~uM&v`jlu z7`gGg(kv6`&J$+O*k2PEvRbLtd>cXAd=NRui)=GVUwHJ<{J8jETRm9eL<$u`ehyU)Bxk2;tvnJBVF>tKjz6iIKP)R`LGX4l@ zy#8uor!9aB$W<*)ik38?b!{ayZP}{YnAj6#9&v5&Z$RlO@d2%!(5sKeYb`Q{eWQ7x zwD_yq4>G&P28P?-14sha@8b3FN-H{9#I~i<*8HZM&TkF?8ea7?ec#ePC1}3i^>Nxb z%Aj%<#Nv1HO0H;YAQ(fYgZro=akMmxPcfeSr)lud+%8r-2?}VyN#v&nw7Pt z?4H1)3Wnnf%L6Z0qNq$0LM6S*U3+g-HE}iK)ZHY3X|iGK-nfst|+@lA$jq zIdj=^QbS%x2*$%~C=F}zSDi(qR_nm%xPo=q`c01zR_+o?L)t~xk}J#eGrx<>bN81+ z)(4S;>j0x31@fRr(>RW9bJcOog|`EpTsP`5Tq&<~wTD$rs`(jSLW{&V*!|rlRX4$>&&NxZ?Znuo}0lQtT3>9}bAhvFOj{s%e4 zD*d57PK5IQ6)@eS>>J-$CVzHG{;RQzuagEo0;uFq09U5;jvsC5d`v*qWL}KMGIhAg~&k%a|%2H zKUU}d$Ka$_|MaL4zW6V#irB%F*gu&i^3L(t_0m5Ozvlpw1b&9D{9lr_U;+rYXDR4U z$_7__0oFW(KQy}gF8(+W1D^xpkTZaF^D9P8qo8}q473B!@rNLCGW{Bi`Xf2Ldm8Io zc|Tk=LH0HUL9xL${NQzjbg5#?*Jn+e6{%{98UAb5WO+34#_<&0@Vu~B%)Rq1<_{Va zvjE1QN1D2(1x|>S5TTcMx=&=2h_7g5o!y%akFCJ}7pQX~nLnFvP3o=!L&q&0T~@wz z9Zgnj*Nq>!i78VQ`2xu2Oo)gHv;v!pCg`$&i<1M?^iT8LP1{Sb z4^)4r#tT;;f$u!L-8G&5EJ?d2^JDbI!M6TgZZ|J3w`AvY*o2^VL5vZb3xTY4Y%ObF zs^oW)uPVw(ehzwnD>B?Uwv7bAJkM0DTJ7G*;;j1>g$LO954z zQF`msYpm=*ac!-YVMtbP87XNp{yNz+UST~bPWJh+qorcYHl(ZnYu#@7j#R-F_Yc^oE28ELqPu?Ox z*+D3;aMf_q7iN?g%!#OPpDsqlgficz1AO~vbCoYKq2*UELC1d+05h$p4n~U!vN#qX z37hWI&N~_djK-jcWn0nx+-3ma(CQVuqImzTBRkj-gW}LMFqaogBL#MM+y`tJanF*->hUOB7+lRWuG7b zobBh|*d)SLm6X5iWo^Jk=QylpeYz5gZOAU~OXD(@C~lDh&}aXl2si~%=swzA=VhNR z-O@E_Fm2^TnZ93@aNm6Svgi~OOt3c1lGkh3nWc-lJ`yu$O0-J3kU5<_(phYvUpFTX zyI@KyS^FtdHsb+#^nr zPfmc_r>V-1_~UM*s=lMY6uefe`uFqfc?o!idXW1NwkJRtr(BGxLvRswkjGujAbo(i zY!S<=^3oU@YcPQqQ8Fih{2Os*_KH)}_G(@;P21j5M@T>0pzV1Og;VfElpEiM2F%wZ z;8O&Mp03#^&Tv|ZI*up1M5|S0`yN5yVy;R$CAIlC7F4~8@Wv>+*^Nxk5QhQEoB4HVQ=>)T zQ;$;#>z}w!g>0y~pWRzqlOaad$vn#JXcvenx z-4r~UQ0yzx`(zB2x<8TYQd+uPIpb^e+(E8`7s!DP%`Dupa2FIvNc9$frV-4sEb=U? z0Zv7qc?wRBN-9M}T^?SuHCa&o=TbosdPB0XPcvWs%rGKaty7AhoS;sV7RSK>@OgPr zmz&wE_`>Q7V=Lr`hXWBU;0`0`I=~N*a1;LfH%saLwU7B{$~>^8zcng<*1J3$_1+>o zOxXi#3IDZQ1D`590UEZyHECd7QIY=*t5jm;#+*dhiARIXk|sl=&ztiO2D4FcyW2bgPWToNISsS4-YQsNpS+$=D7|7s4)$ctCj=GO*+B<+;|6MVx;Mvr=AD_@K>tMPYWIbTGm5!_ zGGCsh*X~Rd1Bky_(<+@Anxmo=?OEYgc(yAw>lrL!Dq8^fcqib{F15)O zAk13Zk=$<;rvoa43etE^=0*aHiEE`Bu!lcjrj!?0x3hBmfu3><$5D#F5e-OzsPCZT zf-bkD18vRG%x>dcYXfc3)c9=m0Aqpq8!_s<pLN6OgU89kqh>`CG56N>z8AAc>K6%y{i)3u{T4aYUW@jJue?H69kbzO}!(>Xu;|t zm;Fi5yuaeDxGm4}HrxR$$&zjY7ck5>WSw7HygLSK z43nHNYQO9(!u;$Sl4G)pNZ1J^srJ_Sq%{}t%i7k)yQ`jdV`!Z6M6}B^5l`J>=rPC& z!%N-@&DzxT6Yc}dyUewYU&7ZMG5vP9vtD?q+R&{w-{@|dp3dq=%%CS_#$7!({Vl@9 z(3PesAFB}n_=s}uoOQItHM3fGu_KA)u)bEO;EX{+ryE)Uw1{>as1CPfrsMflpy-1< z0N?c_q3>F7ju3^)La@*XcK#TDvZo7+LbEZUeJOEcu2BuV{c%8~s+;ODVVO!G5U;L6 z@QRNzEjO(3Z{^1jjF~B;1?NGgaHRQ>Dcm(9zY^s9NyfXV8>(xy7S{AfqfFGq07{`Z zs$iuqx~oOheY6Ku(D>L`W_nSNAz2MzoZ(*CF~bv#F})PP)aR`39!>mJ^y-l2uY3WP z(LOUo^Cw;btR2k$^{2L+;%Ar^2J3V_xO^+%AwlgJI(qqsE^+AG-vdVA_5Yd^_zz!2 z=v3-5{zxnTdcoFL$k^D}H2{JAd$Es3fqwdtc>MlfM-~2ew-?u`h?^~;)EM8`I`rN1 zxp{ecJA#6>rujv8@0=eDNm-mN#W3W_(Zgut_o*hFna)BA^}w-u`JringoI?gC#HO= zbGwI!pet-2EIr&hYh54##D+TYb$fd!a92?*24VTy$3FD%uyzu3fo7&ay!Q+o#)pRD zC48s9&%~eT>rk`Kb$5*Mo2QTK&)YTK!Ibgtn~Ya{zaJ9{8@L2;+#zu+ps%e$qJ4u1 ztJxwBqTbz!%hd)>%1di{dmmn{Jx}c*jxUH>A4KuWcUl{OHYb{S%L*GcV`QYxcbYUe zb*k_*cWUk^ZxtA1UwH#>8&AE?qX&O`npB8TG0>%gEq{0@l@3-x_{o-{CjEi;2W`#v zEtuTdhpF`L6(;=SAH%%U&O+l3)<|%t%OwJd(qb1W^b&-gbxQK5QO8USAYa{eGAN(f z$c-2}4k>(8dPNuV9IP|Hrd+ImbGt*(MNx(AuhgVo(z7Z^Q9=t)ns|P}4g$WB_ zJ>*H+!5`U533ywGwMhGCc?H>tG8K^*0=$w{LEGQQwp~0$o}I&l#Z4#^1dde{lahT-MqkIoHYTrX2=+NTzYEIErL$uW|W&9+z+gd3K+=X5E-Kh z+ed0ogJAv?1dqUxUdfxf7qCh3qjeIgq#I-wHlrsc30m9oeYe-ZUW@qTM?4soy`a_F z*>}{i$PncGz+tsT#=)F0I9rzxr63h`k@~2$(UvHb7MQc*IdKS3Z^vIPNq$Vv3&)|s zhrcDC2k(+BW7m+X2aL&vjqd9>Stl@_dV?Q1vXMRw2y0GT?q<6I3AQ{dmJB|pUKXgf zOe&VPu_65N^7ldZb;NG)C6jA=qdtelkMTC;7jyLtE`?~#dOeVUUWY3_=wMBaRAHlmL%!wQg@#-wZ$M;Mc5p* z#w%@=?E7T1sV|w}_=S_}97{&AeC#=nY$Hxj2FE6AO3{Sgi6F|DD!*g8%VQ%)BY>5) zJ@Ubs0`Tr3Obc$x zpE#|I>tM_J`q`PAwTsU!nuwK0fJbK8Y(l}GteZSn)_LCkooX)SX4#&HPJ-`p<<;AMh^lJMfB zJ|Rjr027J`mL-1HNV>ZFGU<-_cE_>t8lA{riYj?gSEA_F8w+k;CIq(>@Cg{uzV^mc zZ{D29{B|s9F-i^gUB+J7tVAE*pDjX^P|H~|vHQv=cS#3Xw^r5ObDKSha926ix@)@V zoT*Gqdu{-xEDUZ}ZC?~^CD%Smw&ox3V|BNJ>o}N&vhBQ7W#$f~d&s~7GxtjyAAODN z0x@t}zH=2ZP99I+T(Aj z5i2s>VvL3^`)kT($D3icc|b*P$Yk;F@^(uwrE^F!I6_v$0Ey}Kl+0XA`8|NJili5I zrQ~HuE`Rn1>b{S@B2vPd1R2grh)@%zp8hzmtK@+H6O6#{RPJB?H;5Fw2G{}%eq7PVLh?f{3jSH#- zhuY79T+IJ4>;LPT;Nc%c!u>y;6MyL{e?2sBpLUpj_?yw6`{Fa8?D&gVt;!A0^1mbi zzNppzy_c63uJ4%620Xsc8>61(xvQ3`)gtrK%F1F39*?5?;G^i6#$2nYMcpIsFE2tn zd{Y#+9zMlS9hK?jx?gl!=PIcV5Tx*u0+`Yqp@;4`xUnd9pw=2(;Z*4T1Zx^BG**@y z*Xu*-!heuIij-(&ivh!$)#`W|Nc3{|>OHhtkC&I=fvEtxOBCZY6~=WxD~ok>M6I(! zicg)EZ*J4p!Y0dr2#$NcP{PI@+d6k!p%Srb8F0=8K|$v*SMa9 z6C9@0xoGM&@VUO8FdU<&(MCeR4%B6~Zuh)>0(H*RySl=|iaJYjLzPVuh)?=21@rrT z7o~_-1nkwlOr4x5%5M7bs+B*m%C!(I78-}*1x#B+!PKifYD@09DUTYE;&DS=3(Q3@ z8jO#r6Z$p7(q#DQ36K7_$P6?!!Sz)u-Xls)ixmXMzpUl3oH)OI3Bk>2i#!W)1Ccrd z13PE;inT&_`?2Pty|q)2>u($?$1Lr>sDC1)Np%Y_+1XNVFYR2quY61Asd#hN$YVon z6m>aMyLl-RbP6kad|zjRz5J{_dB$wyTV1sHx|q_4V?tepKQ1d`4}gVDFQPPg*l`y< ztRz(ptKTj@O_y0BEZ33V^FtYZANB+dGDPv`@oAb&_pV1-P{ol@KIxWrBl$}I?!t`8`Ey0*K?MzEYEMii1<`0HI=|b zMpkzN7v|65-rt`6UV`3)Ww(l;G|5ntp%P)$ zyA!3V4RFCaC6Wi1E~{(F5d145zL#AiX?++hjMT9m)Prk0B=Fs0=&ZbnXv5jgq2||d zLrD3OQCbg`7#o_kO4o@ak9CWHSkn)W^+kuI#MVkW00<{R>48jel@aSOF#QE%zfg=C z>=0l8&NW+F0xjAG@9m82RZ#>AYHeUzL|+agi2p2M@z0XDt^k@d6QM&Gz)_W5oyfN# ziUV-*%bDMr5r4`sTUaHY4ijuTol_(364sK@mK1A zUuCUqKg60$YB27q`mF+C#6J6ZjYAtD20i0G0Exjd7j>V^3uiyDNqSt}nexD5TH4w6 zK6BNpiMPz4#ow)ukWPCR>W3a+o<0Zi;%ii z4cH$&UYiE8kX&85%>_BYgI03NetPR{H%2A+ZA<8R5<0SK%4t8uAMap0Wk>_%=`6~t z97+d(gS(tQ-&%zSqWQ^sKA1=mS5yZG@=KSsMIBYLL5&`M1!z?wVdwov?yq7?Z7o!> zd7m={Knk;wu69a5 zqP0Oyo^7RF>AQ_SYPxxwdCAxSnqcR_sy1$STj#&JdTNV!q9ZRN@_&*v)Me9mq>aM_fN*A`5-FC?Qo8uO4(bx69H%pK?$o>26O^y}4vOMr z4!Z^KbXh!2>xF!dBkZaV^c!-CaRa8Sa4Bk&#a!NzW!AGcuQWZq^6cBYKDf+QyD!YN z!7Onb9i&pq0$3I*SQM)a3-%jk@{mn9oxQ3)#%5j5cloMYx=5Q$ITCGPlRq|I3xRBf zL~@4EWNyr7AZ`m!Tr(hEd_3^+`}JGo^HN{eQzG5KR4OEDweFIOEzuP8mU6Iw1WY0Q zO=`zTT+67aj#TUpkNo51V0}pK90$-(76y>%mufw6cZ(gj_IlHe%5{qi4s6wBGMUz= zG5?Ycb$&vHY0_6iTdJY=A~8(;eGV&?af7N^lht(w7a%?pcY=8-7ej8gUPCKqRY%&F z@_cFE^xQsprR;CuWJ*G>jN+$4%io(Al*&o2;|;w2bl;DKVj}mq?9#Hd#skf~#T7>| z4+`*5$~|j*-bY`TMR&{<%)nca;URuKUk$mO zqVz>MWn|ZBM2$Nx+GWPE_DxRN6=q=tY>{|;@6wDYT4$7nl8@(Jugzf7XKM>j&?G#% zaT4M~eKQ3eVYjtXWcTK4wtZd|L3>ueJ zaDe)lZ+~Px|NhigKIsx7OIuIfT8jQ)fmtLHeP8sp$cRo)vege)aZI6e;zrXid zy20K0nzxLu&XZVyz2wAv!d>Sm+H+0qm=`${h^~E02xROk2cC?AXMO(vYwo+ln#$U5 zV*?vFHc%ii7DPZmrG_dXRl3v=h>b2t?-&FT6#=CVUFjrLA#?(Qh;%6-QbQ3!3qc@; z&Tj{2?wy%$zI%W7KKFZ`nwbr}OyW4Pzj8;uXeaRk250_Ccl^`#x z<}iNfP;_KT`$hJVlc~qaTi%>}fqXUbhs=89=bz}k;Il!B`Svn#+KH7#gLt5H!>%bFc8eDFQ;%k zC5eJaowT31GiLLP^T44F{doavPe1+=MF926EZQZNT(YrF+r+x7O|;W`k~4+)<36t= zUQ&xs%bV`JeJNmnP4f}O+A*`>8Y$Zy^eg$J$dNY#-%Sw{RDG~Nz>p1uaq{<(63ZV8%xs*=bT+x>78F^_EfJ*S&7;=P{;b>=6TDLkfDP_lJ~(?=QpZ1 zgTxc1uUq z9j>SU3*kSw8-xEx?D=KZp$wBO30!BuSGzRPiB>c4-gdbgKsDsOMXZm zO!t_TOO#B}4Ea-yFG|7GYOkhRobbD}bPbu;u4^Eyls5|=7i{5kP;b78_Zt%YXrZEr6rx5*pX>ueRRZyeWb6R_c5na^l*8J788JMXgx;uuKf6l_tl z=gYZ?(35_bE{3o4D#8Rx@uLl6C)J%}F=#{ZUXF(!i`6CbZ79HV3=M`&UxTp_WgH#t z5?m5DbYv>qwqLXfvRV^Wnr_u|P3@YDDt8HL=!(g@uW|1kmjlFm54s8t93@pOBwyi6 z6zHg0sKym`1}mjyq+*>^!i4$At4mvbJ|j4Gu$)PJG9_!}*UV2e5aLO5Fhs9<>IpRT z#dH2QQSXHs1`jo;Us7PaRP9*8-lW8`_0If!E6@l ziv4Cbez)u~(JiowNIe|f09%Puj9eNY)Te@t0T-wg5MTVdZ|#t~W$OB7y51U)@* zfvIF3anx>f+R2{r!DY-7U-BzuOu1!EHG_f_H^($X{uAR`hLGUOdgM~CvPRD!iE^XY zRXl%<-&Q3f$zC%OX!Gf~$WBnLRHiDCChMy|+ohP4oE&ckamfDDcn7G)SM9}5+m9&n{eyD;yI~JTZsGqOV9@uhZze6{<|-|#s*iC+d#~tZWo22?;l`i+ z@`)GOi&J?+8?-h-ujHoP!g&y>zhTk;8y;MDnvZwlf&TS`+Ly%T5rCc=|H7CZVHvMD znr!?m>Kj2`oQW1%kaGejb~{2JaI^A0HmE$(^I`c`^@iwFFN~INZ9k;D{NC}9L4p;C zFJ^#cdaA3KO|}e|2D=F})QMX-sNg8#=2C3c4Xtn@Y9#UK*y__!qtcHWJ@r2bNYh-k=8B-DL)S=9*=9;FrVy?8#x~% zO1;%s&1`Bsa^Hxkx4aUxS?Djh7oiX9la&W^tc0dEwog+KQ7+DDx=Qr7jn^1%!ZKwr z`wco;BcsQ`#Ww*~?W#ZX>49>b0gR`t|Ilc{@t&1pm_SfZ;~kX!2h?c?qQN~I{au`a za~v9w<3f8z(+)sJrQBaQ7GdUf{JM}RP1~9-3a<=3fbTNx>Xpr`o!iI0VCnUhw8UIvNHN%9Z)-YOR%dWu{A< zx#GSIb;qcqt;uTw_BxLC}8M_WvW{`FZ0N*&NvkRrtz?h;R^UWT58I}?y7Q%>|2$L zQ8q>S+$L(YYVX{NgZmKM-ny3tE~S+!i(D&9*Ui!v4wQPQR67>15#)xW*$-=;snu+m zxqZ&9dkvh&C<2_v@Nasu9I`QHF8=B7Wud>>-?g85&J)#}`O-q$lu?a)=xKyxw^K#7 zCbv>41ef}zF@`wQ>ltJ?eIbPULkXKZsKOHHghevVNrWlWjNI-ah~uf?j?6{PJ3eX@ zsqu49CeOGZ2SMF+VzyohuqOIxO4ATHU|jz{Sok{8z>@r1M7g`$n_=$w3U zQ{QvhaAC{GGIpfK$0J&5mwz~%_|M{!11#)*DV+`0u{v=CC+$jRcZoIM5f3xM!`MIZ zLb|4Q+^2N@`00`AXrG{_x2fpEAYbo zcZtCG+D0~972h0%-Rowr^)Lkj|)PKUAh!@&QAr@#=-`^`_+EGE=L&r<13Ox zN1RgCS?Sr721V^A<`lGyL*#t_vUHdiiClG8$%&sG%qFvHnDhI|U+^*;%@j`)4PoO9g zGHO0e7dm%{u1gL#C5opfMh@n5UKfH!g9PJ##BJ((p?2Q64-2^itbcS}7VD$bm8G9}uGD#9)< zHSZEjiyHFXGzd8AIJ|~KjfMI5SX!lm(l8!l?`M~Pd)Lsn367oFtX2cPH-A+ zr|%>4Nu8Qk*2uS`O_!IRERwaEcXU0&uQp3a8q=aNID{>?ysjrxoy0t@O2Q~{;5L(~ z2@3I4Xr_}R;`!-Zl%YA$dhc{#U0&WbovaCZxW~rT@I0tUIIvj^v8hdY7P{n5>SPZy zfA(zLbBaDXT`a^;*cFj3>yZ@;i@5`W9ihv#TnACSd>fu}RH)L9bljQRITF(s9Es*i zv388bmN~v{jzOB5T5Ye?hHM}V>9|&7GVt zisr-GVdh*l%{)i6gj{@iNL0|(LWKL}*+EZdM*^5HDWXv0MNy7286e*A9E+b+f3}*N zwRyu((Q2{pB6_~k5_W;@Pp&K73t$6_O1xfh{aHXfs- zQX+l4mmf+D4P`<-eAxCE7^#F$CJr@qza+^1hS0W{v^}8z>YX1|j0J>0fD4Amw40xYYimKU&caCjftO97} zpD+V|wu@y%&i^ca{^Ldd3sz=$P)3S&d1f8+U(aW>?SOwiK-J=SaMyZ_0qMMSSBOUhr!@10iNcT-Q?0(91Lti{{1t5PfF(O=1FV zpdTG|O+Ak-)}T*h#JV%PH(%P$S2Hij1iJ=r#n#)i%G}DLfUa@Pan$W-4rQLP#-VLR zJ@ZtRIypSU{?NC_yW2qn{@kGsn)@woOU0YA*)s$^i@2V)p+x0dsR5_>sMhoo*xQL>aQ`l^un1nXSq)on7gN*QMFFC1{(4QG zn`V0_+OWUmcd3jQOGw1zCQ7BZe=|=zg|Q&*uM;gzCxsR>bJxVb(K|NlbO+g)Lb0Q| zvF^FMV;nu`5pC?vnHV%pckVV!;XbJB-pF;Wo5Nn6&LbY6%K%IcUw|gqyDdD;>?_j` zVNEV&W?3mYzV}(Q#)_x^`LEaFNDziaruf_HwflqL?dmS^zDXrss^khR*Mw#A6+_7O z*OF2X2GJhE9I^NLjJz#UIH*c80jyCGvy1~?-n0PX<4JYq0{#-%T}P_x*bO0Pi)a@i z*Vh{Rt5_g7IpE`^m_2C9EVCnBP*~3@W4F)I_c(yZ%%B& ztY23Bsi*O*B(83-5oA$n8u;PPV4Y67oi$ zac17M1?W#|I{!C~+<|~h!+*c>J2Lxw0S}~Ki_zcgw|^0tV55J?*&y_k>?T0AV~q`o z`7N-+$fRd=H6FLfcZ(0s&SkXxCXf=zi+#ms!Esg-G;*UHaz|bP!-Mm!{QBUgn_1h>`^qM3a|(iSEe@0-h2|)Y2n)$L%}Z)4}dI%B4sQ! zF;ePx?MII0lISjiG1s;0dldv2x}Atp$HtsJaAcutOBsd-NfhK`USP$8MT$R3pscij zy;m!fXKbN4;ddZ|joU=3d%C=j?*e?qL&QkBmvkro4G%{BioGc7rohYiIFs%n;WQD< z#3rk>ktcJH(hlfX-v%J3EhagwL|@ZH*dLWvwzfJqGywc8vazp?dF;di8%r4{_{r)! zEtsTn@QH0{1cG5+XB^KyA+mH6vmvi~bwdPXL-fYB;%biZ(ls?MY|vHhP~JkWZ7nCq zY)1ld{)imGOK{y|4`h_R&$Rq9E4D%^<3*TSs$pN0R@F=8o}~vdItT1YSaIMKq`l1S z`~fNdq<$7wt6JcP#MNG2CM`!#_@yaDFyK)O;ahW(K~Ha$%jA)h|UMJk~8>MlTA?$sp#%I*mSB z$rxa~G_gm|7+yc#s}U_XbEB$-`GC}^$hiR-$%P@#ufEa%zLP(nt}Eja+k#^@(mu(P zb}iH1vxN9es<#_5O@3#&if7<)lB8+;DGcTE{^eKdQdAcvOJtt#WrLSC>s0g)l{o_0 z4jY2>U{83QXV9Mg$X7FZc}jevzLQ%`-Fn9>kHT8h*Kx;Q3%f<{j*ZcW4CxcoPyqgJ|%&CUcwL2W&hQ$s<<<4dLPlB-sg{@|MN_b5X8Q0W#J z`;h!d&ITo&!_l#q*n^9B+zJc3mj=_~5dsuoe}HtxM^ztENpL=55xet_i4e2Wlss|2iZud%qeSdj%z;NIzN$AIv^^_$#zdxl+(d$01PYuEW1m4+VdDATAs6P z!RyYNtYBrJ!XQQA&+pm{^kqjV9~+aogO-KM=ZsxnZ$J}HPhzn4k;{{VlDnpAIuhop zWk)@9S|n!Y<{~Fb7Fd4ft8J@7bXr8#p;idH=sSeeN6L-kuhs+1o)^MR4Akrk;xZ)+L^>p$O1BNET{wqYVp zfytxI=o2ptlJ-~qk~!YyGUG;m45ss8yd|y0kzYTb%tODWQHOK}y1R#-DtD}L0=4S% zPn>cw2{Y}9gtO)Ce5}riyuFi8z_R2AAE}nvtrT z!7j!2L3^ym5;YLn0xP@LCpzaB2A+5J8%vpDq`1t8xd4lu8aIqs2#CmCFV}t-)(2$} zg7TfU+uoPR%Y$*l=WAw}(f!NN3h9irNH`(?y&~1C&AG^Z8EdyMUjYP7YRW3XJmf-( zo3Th!90;$Jp0VQ5%18t5wsXkzsd1zWF*6IKDnA~LUgOQvR;C*BV~f^!$(BfT1q*ZN&oqwEDwZzh zgJJcOp>}>#r|oTrtM%6doFb|aLT6j;Y`2sahb$(C&e>n0u}wZ`A5JlY4w>j;D|0O! zT(F3CJM{+mR}6aKy+L}%vX@Xa^mADSwJ>y2bLJ7rxXXR=!=AlA%>rfrgP}6Q+FuJ-N$*Y6;InG)O=}`rSV67#ayI(mR8^?>6&<1(a*DQ3)?*U>R-1>sW zz_hrmlyJ-yFl^Hi@pV>KY|ZeHS~k)y=2B3BxSU6PXLY9gV%2t{TM~}ml;NW>1*i57 zLQ5Px{KU7Y<%^A|K7WO=w8Wke>X8m>*Ah(oy~Q4yLx=YY-*z#Bd$IRfX%`qR)vw}q z*+f`)iK!5jAH;q362=enL3z-iBU2$iEeiP!dkz5Eb@3ppbS-IXda& zK^l`iUj?hI$|CnOQAhoa86Q`AKB!yk~o@9 z{mG{eI%ziF*Z)pP;vw1g9-r@9soVzN(1_gZXYcn}wPw;oMC(7IcI8<>_Y_s)AHfhz zLl1xVWye0{2SXJ9M1Gf~DJMYQ8%D7xHR%Js5@b~2X~?s_+9TI0WHYK+H)HtdEwG+P zhU&WgNloa#==8GYPJ4ld9p0*5Os!8SbEXi5t5z0< zrT#f5{@*0!;DCS3vT77)aspXK@LD||Hc|Myxj|}A5Z|U3nV1dcdTc$jxO+AYF}vG| zoBq@g*pe-30SYg-)g#xuww$svzq7gAxgLyK4UX9}5*#j&Lbs!DbjLYE z;xOvIKDz}1C7BnSny+vv^| zxw$4TRBs+w7*JkrYbBET*s*rtJOc8NPhSZVuPwKgPG2%4U{2R9%Xx*vSUs^35Vgz4AU})<~7iY)ebmRBxPfr zTt-|W)NUKl51&`NIVrSG+}T3n1A{3WQ$wK4PbPcmRE5Jszk)fja3;cx$wT@cZI_<< z7VHc^p)}IggWVquugmVV5ooK#);<(w?#H8L0om{giAuM*nC+=Y+sdeoG89H`bL`mq j_a-j83?2EZ35j)74Xo@8U*OC<{bJRWv~K1r+zI$Ee1z+| literal 38049 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 knwnAA`p renderSamples(Display display, java.util.List rows, Map fonts, int sampleWidth, int sampleHeight, boolean advanced) { @@ -149,6 +159,17 @@ public static void main(String[] args) { advancedCheckbox.setSelection(true); advancedCheckbox.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + Button legacyCheckbox = new Button(shell, SWT.CHECK | SWT.WRAP); + legacyCheckbox.setText("Use legacy GDI text rendering (org.eclipse.swt.internal.win32." + + "useGDITextRenderingWithGDIP = true) - historical, pre-#3091-fix behavior." + + "\nThe legacy fallback is only an escape hatch for the transition to GDI+ text rendering and is to" + + " be removed in a future release, at which point this checkbox will have no effect anymore."); + legacyCheckbox.setSelection(Boolean.getBoolean(USE_GDI_TEXT_RENDERING_WITH_GDIP_PROPERTY)); + legacyCheckbox.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + // The property only ever affects the advanced/GDI+ code path, so the + // checkbox is meaningless (and disabled) while advanced rendering is off. + legacyCheckbox.setEnabled(advancedCheckbox.getSelection()); + ScrolledComposite scroller = new ScrolledComposite(shell, SWT.V_SCROLL | SWT.BORDER); scroller.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); scroller.setExpandHorizontal(true); @@ -181,20 +202,27 @@ public static void main(String[] args) { Runnable refresh = () -> { boolean advanced = advancedCheckbox.getSelection(); + legacyCheckbox.setEnabled(advanced); + boolean legacyFallback = advanced && legacyCheckbox.getSelection(); + System.setProperty(USE_GDI_TEXT_RENDERING_WITH_GDIP_PROPERTY, Boolean.toString(legacyFallback)); Map old = samplesHolder.getAndSet( renderSamples(display, rows, fonts, sampleWidth, sampleHeight, advanced)); old.values().forEach(Image::dispose); - shell.setText("Text rendering comparison (advanced = " + advanced + ")"); - info.setText("GC.setAdvanced(" + advanced + ")" - + "\nToggle the checkbox below to compare plain GDI vs. GDI+ text rendering." + shell.setText("Text rendering comparison (advanced = " + advanced + + ", legacy GDI text rendering = " + legacyFallback + ")"); + info.setText("GC.setAdvanced(" + advanced + "); system property " + + USE_GDI_TEXT_RENDERING_WITH_GDIP_PROPERTY + " = " + legacyFallback + + "\nToggle the checkboxes below to compare plain GDI vs. GDI+ text rendering, and - while" + + " GDI+ is enabled - the default vs. the legacy text rendering path." + " See the source comment for what to expect per row."); shell.layout(true, true); canvas.redraw(); }; advancedCheckbox.addListener(SWT.Selection, e -> refresh.run()); + legacyCheckbox.addListener(SWT.Selection, e -> refresh.run()); refresh.run(); canvas.addPaintListener(e -> {