Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
## [3.2.0-pre.11] - 2024-12-09
### Changes
- Fix TMP crash on Hyphen wrapping.
- Fixed incorrect character caching when font styles and weights are used. UUM-87529
- Fixed the iOS crash when using fallback fonts created at runtime.
- Fix exception thrown when pasting text into TMP inputfield with custom validator.
- Avoid creating a new submesh if the previous one still has space.
- Fixed the broken URL of the help button on the TextMesh Pro Settings page.
  • Loading branch information
Unity Technologies committed Dec 9, 2024
1 parent 053c344 commit 49623db
Show file tree
Hide file tree
Showing 16 changed files with 376 additions and 115 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
# Changelog
These are the release notes for the TextMesh Pro UPM package which was first introduced with Unity 2018.1. Please see the following link for the Release Notes for prior versions of TextMesh Pro. http://digitalnativestudios.com/forum/index.php?topic=1363.0

## [3.2.0-pre.11] - 2024-12-09
### Changes
- Fix TMP crash on Hyphen wrapping.
- Fixed incorrect character caching when font styles and weights are used. UUM-87529
- Fixed the iOS crash when using fallback fonts created at runtime.
- Fix exception thrown when pasting text into TMP inputfield with custom validator.
- Avoid creating a new submesh if the previous one still has space.
- Fixed the broken URL of the help button on the TextMesh Pro Settings page.

## [3.2.0-pre.10] - 2024-05-27
### Changes
- Ensure space and underline are always added to Static FontAsset. (UUM-45512)
Expand Down
Binary file modified Package Resources/TMP Examples & Extras.unitypackage
Binary file not shown.
2 changes: 1 addition & 1 deletion Scripts/Editor/TMP_BaseShaderGUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ protected void DoColor(string name, string label)
{
MaterialProperty property = BeginProperty(name);
s_TempLabel.text = label;
Color value = EditorGUI.ColorField(EditorGUILayout.GetControlRect(), s_TempLabel, property.colorValue, false, true, true);
Color value = EditorGUI.ColorField(EditorGUILayout.GetControlRect(), s_TempLabel, property.colorValue, false, true, false);
if (EndProperty())
{
property.colorValue = value;
Expand Down
2 changes: 1 addition & 1 deletion Scripts/Editor/TMP_EditorResourceManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ internal static void InitializeFontAssetResourceChangeCallBacks()
string fontAssetPath = AssetDatabase.GUIDToAssetPath(fontAssetGUIDs[i]);
TMP_FontAsset fontAsset = AssetDatabase.LoadAssetAtPath<TMP_FontAsset>(fontAssetPath);

if (fontAsset != null && (fontAsset.atlasPopulationMode == AtlasPopulationMode.Dynamic || fontAsset.atlasPopulationMode == AtlasPopulationMode.DynamicOS) && fontAsset.clearDynamicDataOnBuild && fontAsset.atlasTexture.width != 0)
if (fontAsset != null && (fontAsset.atlasPopulationMode == AtlasPopulationMode.Dynamic || fontAsset.atlasPopulationMode == AtlasPopulationMode.DynamicOS) && fontAsset.clearDynamicDataOnBuild && fontAsset.atlasTexture.width > 1)
{
Debug.Log("Clearing [" + fontAsset.name + "] dynamic font asset data.");
fontAsset.ClearCharacterAndGlyphTablesInternal();
Expand Down
2 changes: 1 addition & 1 deletion Scripts/Editor/TMP_SettingsEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ public override void OnGUI(string searchContext)
{
// Lazy creation that supports domain reload
if (m_ResourceImporter == null)
m_ResourceImporter = new TMP_PackageResourceImporter();
m_ResourceImporter = new TMP_PackageResourceImporter(logErrors: false);

m_ResourceImporter.OnGUI();
}
Expand Down
14 changes: 14 additions & 0 deletions Scripts/Editor/TMP_SpriteAssetEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ public override void OnInspectorGUI()
if (GUI.Button(rect, new GUIContent("Update Sprite Asset")))
{
TMP_SpriteAssetMenu.UpdateSpriteAsset(m_SpriteAsset);
ResetSelectionNextFrame();
}
EditorGUI.indentLevel = 1;

Expand Down Expand Up @@ -677,6 +678,19 @@ public override void OnInspectorGUI()

}

private void ResetSelectionNextFrame()
{
var activeObject = Selection.activeObject;
EditorApplication.delayCall += () =>
{
Selection.activeObject = null;
EditorApplication.delayCall += () =>
{
Selection.activeObject = activeObject;
};
};
}


/// <summary>
///
Expand Down
12 changes: 5 additions & 7 deletions Scripts/Editor/TMPro_FontAssetCreatorWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,7 @@ public void OnEnable()
}

// Get potential font face and styles for the current font.
if (m_SourceFont != null)
m_SourceFontFaces = GetFontFaces();
m_SourceFontFaces = GetFontFaces();

ClearGeneratedData();
}
Expand Down Expand Up @@ -438,8 +437,7 @@ void DrawControls()
{
m_SelectedFontAsset = null;
m_IsFontAtlasInvalid = true;
if (m_SourceFont != null)
m_SourceFontFaces = GetFontFaces();
m_SourceFontFaces = GetFontFaces();
m_SourceFontFaceIndex = 0;
}

Expand Down Expand Up @@ -1220,7 +1218,8 @@ void ClearGeneratedData()
/// <returns></returns>
string[] GetFontFaces()
{
FontEngine.LoadFontFace(m_SourceFont, 0, 0);
if (FontEngine.LoadFontFace(m_SourceFont, 0, 0) != FontEngineError.Success)
return Array.Empty<string>();
return FontEngine.GetFontFaces();
}

Expand Down Expand Up @@ -1845,8 +1844,7 @@ void LoadFontCreationSettings(FontAssetCreationSettings settings)
{
m_SourceFont = AssetDatabase.LoadAssetAtPath<Font>(AssetDatabase.GUIDToAssetPath(settings.sourceFontFileGUID));
m_SourceFontFaceIndex = settings.faceIndex;
if (m_SourceFont != null)
m_SourceFontFaces = GetFontFaces();
m_SourceFontFaces = GetFontFaces();
m_PointSizeSamplingMode = settings.pointSizeSamplingMode;
m_PointSize = settings.pointSize;
m_Padding = settings.padding;
Expand Down
76 changes: 70 additions & 6 deletions Scripts/Runtime/TMP_FontAsset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,36 @@ static TMP_FontAsset CreateFontAssetInstance(Font font, int atlasPadding, GlyphR
internal static Func<Font, string> SetSourceFontGUID;
#endif

/// <summary>
/// Weak reference to all <see cref="TMP_FontAsset"/> instances.
/// </summary>
static readonly List<WeakReference<TMP_FontAsset>> s_CallbackInstances = new();

/// <summary>
/// Register an instance for static lookup.
/// </summary>
/// <param name="instance">The instance to register.</param>
void RegisterCallbackInstance(TMP_FontAsset instance)
{
// Verify that it is not already registered.
for (var i = 0; i < s_CallbackInstances.Count; i++)
{
if (s_CallbackInstances[i].TryGetTarget(out TMP_FontAsset fa) && fa == instance)
return;
}

for (var i = 0; i < s_CallbackInstances.Count; i++)
{
if (!s_CallbackInstances[i].TryGetTarget(out _))
{
s_CallbackInstances[i] = new WeakReference<TMP_FontAsset>(instance);
return;
}
}

s_CallbackInstances.Add(new WeakReference<TMP_FontAsset>(this));
}

// Profiler Marker declarations
private static ProfilerMarker k_ReadFontAssetDefinitionMarker = new ProfilerMarker("TMP.ReadFontAssetDefinition");
private static ProfilerMarker k_AddSynthesizedCharactersMarker = new ProfilerMarker("TMP.AddSynthesizedCharacters");
Expand Down Expand Up @@ -794,6 +824,8 @@ public void ReadFontAssetDefinition()

IsFontAssetLookupTablesDirty = false;

RegisterCallbackInstance(this);

k_ReadFontAssetDefinitionMarker.End();
}

Expand Down Expand Up @@ -893,6 +925,28 @@ internal void InitializeCharacterLookupDictionary()
m_MissingUnicodesFromFontFile.Clear();
}

internal void ClearFallbackCharacterTable()
{
var keysToRemove = new List<uint>();

foreach (var characterLookup in m_CharacterLookupDictionary)
{
var character = characterLookup.Value;

// Collect the keys to remove
if (character.textAsset != this)
{
keysToRemove.Add(characterLookup.Key);
}
}

// Now remove the collected keys
foreach (var key in keysToRemove)
{
m_CharacterLookupDictionary.Remove(key);
}
}

internal void InitializeLigatureSubstitutionLookupDictionary()
{
if (m_FontFeatureTable.m_LigatureSubstitutionRecordLookup == null)
Expand Down Expand Up @@ -1091,12 +1145,15 @@ void AddSynthesizedCharacter(uint unicode, bool isFontFaceLoaded, bool addImmedi

//internal HashSet<int> FallbackSearchQueryLookup = new HashSet<int>();

internal void AddCharacterToLookupCache(uint unicode, TMP_Character character)
internal void AddCharacterToLookupCache(uint unicode, TMP_Character character, FontStyles fontStyle = FontStyles.Normal, FontWeight fontWeight = FontWeight.Regular, bool isAlternativeTypeface = false)
{
m_CharacterLookupDictionary.Add(unicode, character);
uint lookupKey = unicode;

// Compute composite lookup key if a font style or weight is used.
if (fontStyle != FontStyles.Normal || fontWeight != FontWeight.Regular)
lookupKey = (((isAlternativeTypeface ? 0x80u : 0u) | ((uint)fontStyle << 4) | ((uint)fontWeight / 100)) << 24) | unicode;

// Add font asset to fallback references.
//FallbackSearchQueryLookup.Add(character.textAsset.instanceID);
m_CharacterLookupDictionary.TryAdd(lookupKey, character);
}

/// <summary>
Expand Down Expand Up @@ -2381,7 +2438,7 @@ internal bool TryAddGlyphInternal(uint glyphIndex, out Glyph glyph)
}

// Add glyph which did not fit in current atlas texture to new atlas texture.
if (m_IsMultiAtlasTexturesEnabled)
if (m_IsMultiAtlasTexturesEnabled && m_UsedGlyphRects.Count > 0)
{
// Create new atlas texture
SetupNewAtlasTexture();
Expand Down Expand Up @@ -2588,7 +2645,7 @@ internal bool TryAddCharacterInternal(uint unicode, out TMP_Character character)
}

// Add glyph which did not fit in current atlas texture to new atlas texture.
if (m_IsMultiAtlasTexturesEnabled)
if (m_IsMultiAtlasTexturesEnabled && m_UsedGlyphRects.Count > 0)
{
// Create new atlas texture
SetupNewAtlasTexture();
Expand Down Expand Up @@ -3375,6 +3432,13 @@ public void ClearFontAssetData(bool setAtlasSizeToZero = false)

ReadFontAssetDefinition();

// Clear fallback character table for all other fontAssets, in case they were refereing this one.
for (var i = 0; i < s_CallbackInstances.Count; i++)
if (s_CallbackInstances[i].TryGetTarget(out var target) && target != this)
target.ClearFallbackCharacterTable();

TMPro_EventManager.ON_FONT_PROPERTY_CHANGED(true, this);

//TMP_ResourceManager.RebuildFontAssetCache();

#if UNITY_EDITOR
Expand Down
104 changes: 61 additions & 43 deletions Scripts/Runtime/TMP_FontAssetUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,39 @@ public static TMP_Character GetCharacterFromFontAsset(uint unicode, TMP_FontAsse
private static TMP_Character GetCharacterFromFontAsset_Internal(uint unicode, TMP_FontAsset sourceFontAsset, bool includeFallbacks, FontStyles fontStyle, FontWeight fontWeight, out bool isAlternativeTypeface)
{
isAlternativeTypeface = false;
TMP_Character character = null;
TMP_Character character;

#region FONT WEIGHT AND FONT STYLE HANDLING
// Determine if a font weight or style is used. If so check if an alternative typeface is assigned for the given weight and / or style.
bool isItalic = (fontStyle & FontStyles.Italic) == FontStyles.Italic;

if (isItalic || fontWeight != FontWeight.Regular)
{
// Check if character is already cached using the composite unicode value the takes into consideration the font style and weight
uint compositeUnicodeLookupKey = ((0x80u | ((uint)fontStyle << 4) | ((uint)fontWeight / 100)) << 24) | unicode;
if (sourceFontAsset.characterLookupTable.TryGetValue(compositeUnicodeLookupKey, out character))
{
// Set isAlternativeTypeface
isAlternativeTypeface = true;

if (character.textAsset is not null)
return character;

// Remove character from lookup table
sourceFontAsset.characterLookupTable.Remove(unicode);
}
else if (sourceFontAsset.characterLookupTable.TryGetValue(compositeUnicodeLookupKey & 0x7FFFFFFF, out character))
{
// Set isAlternativeTypeface
isAlternativeTypeface = false;

if (character.textAsset is not null)
return character;

// Remove character from lookup table
sourceFontAsset.characterLookupTable.Remove(unicode);
}

// Get reference to the font weight pairs of the given font asset.
TMP_FontWeightPair[] fontWeights = sourceFontAsset.fontWeightTable;

Expand Down Expand Up @@ -114,7 +139,7 @@ private static TMP_Character GetCharacterFromFontAsset_Internal(uint unicode, TM
{
if (temp.characterLookupTable.TryGetValue(unicode, out character))
{
if (character.textAsset != null)
if (character.textAsset is not null)
{
isAlternativeTypeface = true;
return character;
Expand All @@ -132,32 +157,21 @@ private static TMP_Character GetCharacterFromFontAsset_Internal(uint unicode, TM

return character;
}

// Check if the source font file contains the requested character.
//if (TryGetCharacterFromFontFile(unicode, fontAsset, out characterData))
//{
// isAlternativeTypeface = true;

// return characterData;
//}

// If we find the requested character, we add it to the font asset character table
// and return its character data.
// We also add this character to the list of characters we will need to add to the font atlas.
// We assume the font atlas has room otherwise this font asset should not be marked as dynamic.
// Alternatively, we could also add multiple pages of font atlas textures (feature consideration).
}

// At this point, we were not able to find the requested character in the alternative typeface
// so we check the source font asset and its potential fallbacks.
}

// Search potential fallbacks of the source font asset
if (includeFallbacks && sourceFontAsset.fallbackFontAssetTable != null)
return SearchFallbacksForCharacter(unicode, sourceFontAsset, fontStyle, fontWeight, out isAlternativeTypeface);

return null;
}
#endregion

// Search the source font asset for the requested character.
// Search the source font asset for the requested character
if (sourceFontAsset.characterLookupTable.TryGetValue(unicode, out character))
{
if (character.textAsset != null)
if (character.textAsset is not null)
return character;

// Remove character from lookup table
Expand All @@ -171,36 +185,40 @@ private static TMP_Character GetCharacterFromFontAsset_Internal(uint unicode, TM
}

// Search fallback font assets if we still don't have a valid character and include fallback is set to true.
if (character == null && includeFallbacks && sourceFontAsset.fallbackFontAssetTable != null)
{
// Get reference to the list of fallback font assets.
List<TMP_FontAsset> fallbackFontAssets = sourceFontAsset.fallbackFontAssetTable;
int fallbackCount = fallbackFontAssets.Count;
if (includeFallbacks && sourceFontAsset.fallbackFontAssetTable != null)
return SearchFallbacksForCharacter(unicode, sourceFontAsset, fontStyle, fontWeight, out isAlternativeTypeface);

return null;
}

if (fallbackCount == 0)
return null;
private static TMP_Character SearchFallbacksForCharacter(uint unicode, TMP_FontAsset sourceFontAsset, FontStyles fontStyle, FontWeight fontWeight, out bool isAlternativeTypeface)
{
isAlternativeTypeface = false;

for (int i = 0; i < fallbackCount; i++)
{
TMP_FontAsset temp = fallbackFontAssets[i];
// Get reference to the list of fallback font assets.
List<TMP_FontAsset> fallbackFontAssets = sourceFontAsset.fallbackFontAssetTable;
int fallbackCount = fallbackFontAssets.Count;

if (temp == null)
continue;
if (fallbackCount == 0)
return null;

int id = temp.instanceID;
for (int i = 0; i < fallbackCount; i++)
{
TMP_FontAsset temp = fallbackFontAssets[i];

// Try adding font asset to search list. If already present skip to the next one otherwise check if it contains the requested character.
if (k_SearchedAssets.Add(id) == false)
continue;
if (temp == null)
continue;

// Add reference to this search query
//sourceFontAsset.FallbackSearchQueryLookup.Add(id);
int id = temp.instanceID;

character = GetCharacterFromFontAsset_Internal(unicode, temp, true, fontStyle, fontWeight, out isAlternativeTypeface);
// Try adding font asset to search list. If already present skip to the next one otherwise check if it contains the requested character.
if (k_SearchedAssets.Add(id) == false)
continue;

if (character != null)
return character;
}
TMP_Character character = GetCharacterFromFontAsset_Internal(unicode, temp, true, fontStyle, fontWeight, out isAlternativeTypeface);

if (character != null)
return character;
}

return null;
Expand Down
Loading

0 comments on commit 49623db

Please sign in to comment.