void AGameplayDebuggingHUDComponent::CalulateStringSize(const AGameplayDebuggingHUDComponent::FPrintContext& DefaultContext, UFont* Font, const FString& InString, float& OutX, float& OutY ) { #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) FString String = InString; const FRegexPattern ElementRegexPattern(TEXT("\\{.*?\\}")); FRegexMatcher ElementRegexMatcher(ElementRegexPattern, String); while (ElementRegexMatcher.FindNext()) { int32 AttributeListBegin = ElementRegexMatcher.GetCaptureGroupBeginning(0); int32 AttributeListEnd = ElementRegexMatcher.GetCaptureGroupEnding(0); String.RemoveAt(AttributeListBegin, AttributeListEnd - AttributeListBegin); ElementRegexMatcher = FRegexMatcher(ElementRegexPattern, String); } OutX = OutY = 0; if (DefaultContext.Canvas != NULL) { DefaultContext.Canvas->StrLen(Font != NULL ? Font : DefaultContext.Font, String, OutX, OutY); } #endif }
void FRichTextMarkupProcessing::ParseLineRanges(const FString& Input, const TArray<FTextRange>& LineRanges, TArray<FTextLineParseResults>& LineParseResultsArray) const { // Special regular expression pattern for matching rich text markup elements. IE: <ElementName AttributeName="AttributeValue">Content</> FRegexPattern ElementRegexPattern( TEXT("<([\\w\\d\\.]+)((?: (?:[\\w\\d\\.]+=(?>\".*?\")))+)?(?:(?:/>)|(?:>(.+?)</>))") ); FRegexMatcher ElementRegexMatcher(ElementRegexPattern, Input); // Parse line ranges, creating line parse results and run parse results. for(int32 i = 0; i < LineRanges.Num(); ++i) { FTextLineParseResults LineParseResults; LineParseResults.Range = LineRanges[i]; // Limit the element regex matcher to the current line. ElementRegexMatcher.SetLimits(LineParseResults.Range.BeginIndex, LineParseResults.Range.EndIndex); // Iterate through the line, each time trying to find a match for the element regex, adding it as a run and any intervening text as another run. int32 LastRunEnd = LineParseResults.Range.BeginIndex; while(ElementRegexMatcher.FindNext()) { int32 ElementBegin = ElementRegexMatcher.GetMatchBeginning(); int32 ElementEnd = ElementRegexMatcher.GetMatchEnding(); FTextRange OriginalRange(ElementBegin, ElementEnd); // Capture Group 1 is the element name. int32 ElementNameBegin = ElementRegexMatcher.GetCaptureGroupBeginning(1); int32 ElementNameEnd = ElementRegexMatcher.GetCaptureGroupEnding(1); // Name FString ElementName = Input.Mid(ElementNameBegin, ElementNameEnd - ElementNameBegin); // Capture Group 2 is the attribute list. int32 AttributeListBegin = ElementRegexMatcher.GetCaptureGroupBeginning(2); int32 AttributeListEnd = ElementRegexMatcher.GetCaptureGroupEnding(2); // Capture Group 3 is the content. int32 ElementContentBegin = ElementRegexMatcher.GetCaptureGroupBeginning(3); int32 ElementContentEnd = ElementRegexMatcher.GetCaptureGroupEnding(3); FTextRange ContentRange(ElementContentBegin, ElementContentEnd); TMap<FString, FTextRange> Attributes; if(AttributeListBegin != INDEX_NONE && AttributeListEnd != INDEX_NONE) { FRegexPattern AttributeRegexPattern( TEXT("([\\w\\d\\.]+)=(?>\"(.*?)\")") ); FRegexMatcher AttributeRegexMatcher(AttributeRegexPattern, Input); AttributeRegexMatcher.SetLimits(AttributeListBegin, AttributeListEnd); // Iterate through the attribute list, each time trying to find a match for the attribute regex. while(AttributeRegexMatcher.FindNext()) { // Capture Group 1 is the attribute key. int32 AttributeKeyBegin = AttributeRegexMatcher.GetCaptureGroupBeginning(1); int32 AttributeKeyEnd = AttributeRegexMatcher.GetCaptureGroupEnding(1); // Capture Group 2 is the attribute value. int32 AttributeValueBegin = AttributeRegexMatcher.GetCaptureGroupBeginning(2); int32 AttributeValueEnd = AttributeRegexMatcher.GetCaptureGroupEnding(2); // Attribute Attributes.Add(Input.Mid(AttributeKeyBegin, AttributeKeyEnd - AttributeKeyBegin), FTextRange(AttributeValueBegin, AttributeValueEnd)); } } // Add intervening run to line. FTextRange InterveningRunRange(LastRunEnd, ElementBegin); if(!InterveningRunRange.IsEmpty()) { FTextRunParseResults InterveningRunParseResults(FString(), InterveningRunRange); LastRunEnd = ElementBegin; LineParseResults.Runs.Add(InterveningRunParseResults); } // Add element run to line. FTextRunParseResults RunParseResults(ElementName, OriginalRange, ContentRange); RunParseResults.MetaData = Attributes; LineParseResults.Runs.Add(RunParseResults); LastRunEnd = ElementEnd; } // Add dangling run to line. FTextRange InterveningRunRange(LastRunEnd, LineParseResults.Range.EndIndex); if(!InterveningRunRange.IsEmpty()) { FTextRunParseResults InterveningRunParseResults(FString(), InterveningRunRange); LastRunEnd = LineParseResults.Range.EndIndex; LineParseResults.Runs.Add(InterveningRunParseResults); } // Add blank, empty run if none are present. if(LineParseResults.Runs.Num() == 0) { FTextRunParseResults EmptyRunParseResults(FString(), LineParseResults.Range); LastRunEnd = EmptyRunParseResults.OriginalRange.EndIndex; LineParseResults.Runs.Add(EmptyRunParseResults); } LineParseResultsArray.Add(LineParseResults); } }