|
19 | 19 | import java.util.Collections; |
20 | 20 | import java.util.Enumeration; |
21 | 21 | import java.util.HashMap; |
22 | | -import java.util.Iterator; |
23 | 22 | import java.util.List; |
24 | 23 | import java.util.Map; |
25 | 24 | import java.util.MissingResourceException; |
@@ -164,23 +163,22 @@ public Font getItalicFont() { |
164 | 163 | } |
165 | 164 |
|
166 | 165 | /** |
167 | | - * Add any fonts that were allocated for this record to the |
168 | | - * stale fonts. Anything that matches the default font will |
169 | | - * be skipped. |
170 | | - * @param defaultFont The system default. |
| 166 | + * Return all of the fonts allocated by the receiver, that is the base |
| 167 | + * font and whichever styled variants have been realized so far. |
| 168 | + * @return the allocated fonts, never <code>null</code> |
171 | 169 | */ |
172 | | - void addAllocatedFontsToStale(Font defaultFont) { |
173 | | - //Return all of the fonts allocated by the receiver. |
174 | | - //if any of them are the defaultFont then don't bother. |
175 | | - if (defaultFont != baseFont && baseFont != null) { |
176 | | - staleFonts.add(baseFont); |
| 170 | + List<Font> getAllocatedFonts() { |
| 171 | + List<Font> allocatedFonts = new ArrayList<>(3); |
| 172 | + if (baseFont != null) { |
| 173 | + allocatedFonts.add(baseFont); |
177 | 174 | } |
178 | | - if (defaultFont != boldFont && boldFont != null) { |
179 | | - staleFonts.add(boldFont); |
| 175 | + if (boldFont != null) { |
| 176 | + allocatedFonts.add(boldFont); |
180 | 177 | } |
181 | | - if (defaultFont != italicFont && italicFont != null) { |
182 | | - staleFonts.add(italicFont); |
| 178 | + if (italicFont != null) { |
| 179 | + allocatedFonts.add(italicFont); |
183 | 180 | } |
| 181 | + return allocatedFonts; |
184 | 182 | } |
185 | 183 | } |
186 | 184 |
|
@@ -368,7 +366,10 @@ public FontRegistry(Display display) { |
368 | 366 | * the <code>Display</code> |
369 | 367 | * @param cleanOnDisplayDisposal |
370 | 368 | * whether all fonts allocated by this <code>FontRegistry</code> |
371 | | - * should be disposed when the display is disposed |
| 369 | + * should be disposed when the display is disposed. If |
| 370 | + * <code>false</code>, this registry never disposes a font by |
| 371 | + * itself; the fonts it allocated are retained until |
| 372 | + * {@link #clearCaches()} disposes them |
372 | 373 | * @since 3.1 |
373 | 374 | */ |
374 | 375 | public FontRegistry(Display display, boolean cleanOnDisplayDisposal) { |
@@ -678,19 +679,19 @@ public Font getItalic(String symbolicName) { |
678 | 679 | */ |
679 | 680 | private FontRecord getFontRecord(String symbolicName) { |
680 | 681 | Assert.isNotNull(symbolicName); |
681 | | - Object result = stringToFontRecord.get(symbolicName); |
682 | | - if (result != null) { |
683 | | - return (FontRecord) result; |
| 682 | + FontRecord existingRecord = stringToFontRecord.get(symbolicName); |
| 683 | + if (existingRecord != null) { |
| 684 | + return existingRecord; |
684 | 685 | } |
685 | 686 |
|
686 | | - result = stringToFontData.get(symbolicName); |
| 687 | + FontData[] existingFontData = stringToFontData.get(symbolicName); |
687 | 688 |
|
688 | 689 | FontRecord fontRecord; |
689 | 690 |
|
690 | | - if (result == null) { |
| 691 | + if (existingFontData == null) { |
691 | 692 | fontRecord = defaultFontRecord(); |
692 | 693 | } else { |
693 | | - fontRecord = createFont(symbolicName, (FontData[]) result); |
| 694 | + fontRecord = createFont(symbolicName, existingFontData); |
694 | 695 | } |
695 | 696 |
|
696 | 697 | if (fontRecord == null) { |
@@ -719,31 +720,14 @@ public boolean hasValueFor(String fontKey) { |
719 | 720 |
|
720 | 721 | @Override |
721 | 722 | protected void clearCaches() { |
722 | | - |
723 | | - Iterator<FontRecord> iterator = stringToFontRecord.values().iterator(); |
724 | | - while (iterator.hasNext()) { |
725 | | - Object next = iterator.next(); |
726 | | - ((FontRecord) next).dispose(); |
727 | | - } |
728 | | - |
729 | | - disposeFonts(staleFonts.iterator()); |
| 723 | + stringToFontRecord.values().forEach(FontRecord::dispose); |
730 | 724 | stringToFontRecord.clear(); |
| 725 | + staleFonts.forEach(Font::dispose); |
731 | 726 | staleFonts.clear(); |
732 | 727 |
|
733 | 728 | displayDisposeHooked.remove(Display.getCurrent()); |
734 | 729 | } |
735 | 730 |
|
736 | | - /** |
737 | | - * Dispose of all of the fonts in this iterator. |
738 | | - * @param iterator over Collection of Font |
739 | | - */ |
740 | | - private void disposeFonts(Iterator<Font> iterator) { |
741 | | - while (iterator.hasNext()) { |
742 | | - Object next = iterator.next(); |
743 | | - ((Font) next).dispose(); |
744 | | - } |
745 | | - } |
746 | | - |
747 | 731 | /** |
748 | 732 | * Hook a dispose listener on the SWT display. |
749 | 733 | */ |
@@ -821,16 +805,26 @@ private void put(String symbolicName, FontData[] fontData, boolean update) { |
821 | 805 | return; |
822 | 806 | } |
823 | 807 |
|
824 | | - FontRecord oldFont = stringToFontRecord |
825 | | - .remove(symbolicName); |
826 | 808 | stringToFontData.put(symbolicName, fontData); |
| 809 | + invalidate(symbolicName); |
827 | 810 | if (update) { |
828 | 811 | fireMappingChanged(symbolicName, existing, fontData); |
829 | 812 | } |
| 813 | + } |
830 | 814 |
|
831 | | - if (oldFont != null) { |
832 | | - oldFont.addAllocatedFontsToStale(defaultFontRecord().getBaseFont()); |
| 815 | + /** |
| 816 | + * Drop the realized font record for the given symbolic name, if any, and |
| 817 | + * defer disposal of the fonts it had allocated until it is safe to dispose |
| 818 | + * them, since they may still be in use. The default font is kept, as it |
| 819 | + * stays in use under its own symbolic name. |
| 820 | + */ |
| 821 | + private void invalidate(String symbolicName) { |
| 822 | + FontRecord replacedRecord = stringToFontRecord.remove(symbolicName); |
| 823 | + if (replacedRecord == null) { |
| 824 | + return; |
833 | 825 | } |
| 826 | + Font defaultFont = defaultFontRecord().getBaseFont(); |
| 827 | + replacedRecord.getAllocatedFonts().stream().filter(font -> font != defaultFont).forEach(staleFonts::add); |
834 | 828 | } |
835 | 829 |
|
836 | 830 | /** |
|
0 commit comments