public static ICharIterator ColorFormat( ICharIterator input, BitmapFont font, bool keepSequences, byte baseAlpha, IReferenceList <Color?> output) { if (input == null) { throw new ArgumentNullException(nameof(input)); } if (font == null) { throw new ArgumentNullException(nameof(font)); } if (input.Length == 0) { return(input); } var builder = StringBuilderPool.Rent(input.Length); ColorFormat(input, builder, font, keepSequences, baseAlpha, output); var iterator = CharIteratorPool.Rent(builder, 0, builder.Length); StringBuilderPool.Return(builder); return(iterator); }
internal void Set( ICharIterator source, bool leaveSourceOpen, Transform transform, bool leaveTransformOpen) { if (!transform.IsValid || transform.OffsetInSource > source.Length) { throw new ArgumentException(nameof(transform)); } if (transform.IsEraser && transform.OffsetInSource + transform.Count > source.Length) { throw new ArgumentOutOfRangeException(nameof(transform)); } _source = source; _leaveSourceOpen = leaveSourceOpen; _leaveTransformOpen = leaveTransformOpen; _transform = transform; _cachedString = null; _isInUse = true; Length = source.Length + (transform.IsEraser ? -transform.Count : transform.Count); }
public static SizeF GetGlyphSprites( this BitmapFont font, ICollection <GlyphSprite> output, ICharIterator text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, float depth, RectangleF?clipRect) { using (var glyphs = (GlyphEnumerator)font.GetGlyphs(text, position)) return(GetSprites(glyphs, output, position, color, rotation, origin, scale, depth, clipRect)); }
protected override TextSegment.GlyphCallbackResult GlyphCallback(ICharIterator source) { if (_isObscured) { return(new TextSegment.GlyphCallbackResult(_obscureChar.ToRepeatingIterator(source.Length), leaveOpen: false)); } if (!_isMultiLined) { var builder = StringBuilderPool.Rent(source.Length); for (int i = 0; i < source.Length; i++) { char current = source.GetCharacter16(i); if (current != '\n') { builder.Append(current); } } var iter = builder.ToIterator(); StringBuilderPool.Return(builder); return(new TextSegment.GlyphCallbackResult(iter, leaveOpen: false)); } return(base.GlyphCallback(source)); }
private Transform(bool isEraser, int offsetInSource, ICharIterator insertionData, int offset, int count) { IsEraser = isEraser; OffsetInSource = offsetInSource; InsertionData = insertionData; Offset = offset; Count = count; }
internal void Set(BitmapFont font, ICharIterator iterator, Vector2 position) { _disposed = false; _font = font; _iterator = iterator; _position = position; Reset(); }
public Transform( int offsetInSource, ICharIterator insertionData, int offset, int count) : this(false, offsetInSource, insertionData, offset, count) { if (insertionData == null) { throw new ArgumentNullException(nameof(insertionData)); } }
/// <summary> /// Gets a candidate for a ticket reference string. This isn't a full parsing operation; it only looks for strings /// which look like they might be valid. /// </summary> /// <returns>The candidate ticket reference.</returns> /// <param name="iterator">Iterator.</param> /// <param name="charactersConsumed">Characters consumed.</param> string GetCandidateTicketReference(ICharIterator iterator, out int charactersConsumed) { string projectCode = String.Empty, ticketNumber = String.Empty; bool finishedProjectRef = false; charactersConsumed = 0; if (!IsValidBeginningOfTicketReference(iterator)) { return(null); } for (var peekPosition = 1; ; peekPosition++) { var currentPeek = iterator.PeekChar(peekPosition); if (!currentPeek.IsAlphaNumeric()) { break; } if (!finishedProjectRef) { if (currentPeek.IsAlpha()) { projectCode = projectCode + currentPeek; continue; } finishedProjectRef = true; } // If we see an alphabetic character after digits then it's not a valid ticket ref. // Disregard anything found so far. if (currentPeek.IsAlpha()) { return(null); } if (!currentPeek.IsDigit()) { break; } ticketNumber = ticketNumber + currentPeek; charactersConsumed = peekPosition + 1; } if (String.IsNullOrEmpty(ticketNumber)) { return(null); } return(String.Concat(projectCode, ticketNumber)); }
public static IEnumerator <BitmapFont.Glyph> Rent(BitmapFont font, ICharIterator iterator, Vector2 position) { lock (_enumerators) { if (_enumerators.TryTake(out var result)) { result.Set(font, iterator, position); return(result); } } return(new GlyphEnumerator(font, iterator, position)); }
public void Dispose() { if (!_disposed) { _disposed = true; _font = null; _iterator.Dispose(); _iterator = null; GlyphEnumeratorPool.Return(this); } }
Uri GetTicketUri(ICharIterator iterator, out int charactersConsumedInReference) { var ticketReference = referenceParser.GetTicketReference(iterator, out charactersConsumedInReference); if (ticketReference == null) { return(null); } var ticketUri = ticketUriProvider.Value.GetAbsoluteUri(ticketReference); return(ticketUri); }
public SizeF GetGlyphs(ICharIterator iterator, ICollection <Glyph> output) { if (iterator.Length <= 0) { return(SizeF.Empty); } float largestW = 0; Vector2 positionDelta = new Vector2(0, 0); Glyph previousGlyph = new Glyph(); for (int i = 0; i < iterator.Length; i++) { int character = iterator.GetCharacter32(ref i); BitmapFontRegion region = GetCharacterRegion(character); Vector2 newPos = positionDelta; if (region != null) { newPos.X += region.XOffset; newPos.Y += region.YOffset; positionDelta.X += region.XAdvance + LetterSpacing; } if (UseKernings && previousGlyph.FontRegion != null) { if (previousGlyph.FontRegion.Kernings.TryGetValue(character, out int amount)) { positionDelta.X += amount; } } // use previousGlyph to store the new Glyph previousGlyph = new Glyph(character, newPos, region); output.Add(previousGlyph); if (positionDelta.X > largestW) { largestW = positionDelta.X; } if (character == '\n') { positionDelta.Y += LineHeight; positionDelta.X = 0; previousGlyph = default; } } return(new SizeF(largestW, positionDelta.Y + LineHeight)); }
public static ICharIterator Rent( ICharIterator source, bool leaveSourceOpen, TransformCharIterator.Transform transform, bool leaveTransformOpen) { lock (_transformIterators) { if (_transformIterators.TryTake(out var iterator)) { iterator.Set(source, leaveSourceOpen, transform, leaveTransformOpen); return(iterator); } } return(new TransformCharIterator(source, leaveSourceOpen, transform, leaveTransformOpen)); }
public void Dispose() { if (!_leaveSourceOpen) { _source?.Dispose(); } _source = null; if (!_leaveTransformOpen) { _transform.InsertionData?.Dispose(); } _transform = default; IteratorPool.Return(this); }
public void Insert(int index, ICharIterator chars, int offset, int count, bool useColorFormat) { if (index > CurrentText.Length) { throw new ArgumentOutOfRangeException(nameof(index)); } var transform = new TransformCharIterator.Transform(offsetInSource: index, chars, offset, count); // leave source open as we dispose CurrentText in SetText() using (var iter = IteratorPool.Rent( CurrentText, leaveSourceOpen: true, transform, leaveTransformOpen: true)) { SetText(_font, iter, useColorFormat); } BuildSprites(measure: false); }
public static unsafe void AppendIterator(this StringBuilder builder, ICharIterator iterator, int offset, int count) { if (count > iterator.Length) { throw new ArgumentOutOfRangeException(nameof(count)); } if (offset + count > iterator.Length) { throw new ArgumentOutOfRangeException(nameof(offset)); } builder.EnsureCapacity(count); for (int i = 0; i < count; i++) { builder.Append(iterator.GetCharacter16(i + offset)); } }
public TicketReference GetTicketReference(ICharIterator iterator, out int charactersConsumed) { var refString = GetCandidateTicketReference(iterator, out charactersConsumed); if (String.IsNullOrEmpty(refString)) { charactersConsumed = 0; return(null); } var ticketRef = referenceParser.ParseReferece(refString); if (ticketRef == null) { charactersConsumed = 0; return(null); } return(ticketRef); }
public static void Return(ICharIterator iterator) { if (iterator == null) { return; } if (iterator is TransformCharIterator transformIterator) { lock (_transformIterators) { if (transformIterator._isInUse && _transformIterators.Count < PoolCapacity) { _transformIterators.Add(transformIterator); transformIterator._isInUse = false; } } } else { throw new ArgumentException("The iterator was not rented from this pool.", nameof(iterator)); } }
// TODO: Think of adding a font selecting char as first char in a sequence // and use a specialized font collection instead of only a BitmapFont property (mostly in UIText). // Switching fonts while building will need some work, but applying the color format should be the same. private static CharSequence GetSequence( ICharIterator input, int start, Span <char> output) { int tail = start; while (tail < input.Length) { // don't bother going beyond text length or 15 chars // ("255,255,255,255" is 15 chars, hex is smaller than that) tail++; if (tail == input.Length) { return(CharSequence.Invalid); } int length = tail - start; char tailChar = input.GetCharacter16(tail); if (tailChar == ']' || tailChar == '§') { // we reached the end and know the length of the sequence // we can't really use for (int i = 0; i < length; i++) { output[i] = input.GetCharacter16(start + i); } return(new CharSequence(tail, length)); } if (length > 15) { return(CharSequence.Invalid); } } return(CharSequence.Invalid); }
public GlyphEnumerator(BitmapFont font, ICharIterator iterator, Vector2 position) { Set(font, iterator, position); }
public static void ColorFormat( ICharIterator input, StringBuilder textOutput, BitmapFont font, bool keepSequences, byte baseAlpha, ICollection <Color?> colorOutput) { if (input == null) { throw new ArgumentNullException(nameof(input)); } if (textOutput == null) { throw new ArgumentNullException(nameof(textOutput)); } if (font == null) { throw new ArgumentNullException(nameof(font)); } if (input.Length == 0) { return; } Span <byte> colorBuffer = stackalloc byte[4]; Span <char> charBuffer = stackalloc char[2]; Span <char> sequenceBuffer = stackalloc char[16]; Color? currentColor = null; bool inSequence = false; for (int i = 0; i < input.Length; i++) { void AddAtLoopIndex(Span <char> buffer, ref int index) { if (index >= input.Length) { return; } int utf32 = input.GetCharacter32(ref index); int count = ConvertFromUtf32(utf32, buffer); bool addColor = colorOutput != null && font.ContainsCharacterRegion(utf32); for (int utfIndex = 0; utfIndex < count; utfIndex++) { if (addColor) { colorOutput.Add(currentColor); } textOutput.Append(buffer[utfIndex]); } } if (input.GetCharacter16(i) != '§') { AddAtLoopIndex(charBuffer, ref i); continue; } if (inSequence) { if (keepSequences) { AddAtLoopIndex(charBuffer, ref i); } currentColor = null; inSequence = false; } else { i++; if (i < input.Length) { if (input.GetCharacter16(i) == '[') { var sequence = GetSequence(input, i + 1, sequenceBuffer); if (sequence.Tail > 0) { if (colorOutput != null) { currentColor = sequenceBuffer[0] == '#' ? GetHexColor(colorBuffer, sequenceBuffer, sequence.Length, baseAlpha) : GetRgba(colorBuffer, sequenceBuffer, sequence.Length, baseAlpha); } if (!keepSequences) { i = sequence.Tail + 1; } else { colorOutput.Add(currentColor); textOutput.Append('§'); } inSequence = true; } } } AddAtLoopIndex(charBuffer, ref i); } } }
bool IsValidBeginningOfTicketReference(ICharIterator iterator) => iterator.CurrentChar == BeginningCharacter;
public TransformCharIterator( ICharIterator source, bool leaveSourceOpen, Transform transform, bool leaveTransformOpen) { Set(source, leaveSourceOpen, transform, leaveTransformOpen); }
public void Append(ICharIterator chars) { Insert(_segment.CurrentText.Length, chars); }
public static void AppendIterator(this StringBuilder builder, ICharIterator iterator) { AppendIterator(builder, iterator, 0, iterator.Length); }
public IEnumerator <Glyph> GetGlyphs(ICharIterator text, Vector2 position = default) { return(GlyphEnumeratorPool.Rent(this, text, position)); }
protected virtual TextSegment.GlyphCallbackResult GlyphCallback(ICharIterator source) { return(new TextSegment.GlyphCallbackResult(source, leaveOpen: true)); }
public GlyphCallbackResult(ICharIterator iterator, bool leaveOpen) { Iterator = iterator; LeaveOpen = leaveOpen; }
public void Insert(int index, ICharIterator chars) { Insert(index, chars, _usedColorFormat); }
public void Insert(int index, ICharIterator chars) { _segment.Insert(index, chars, AllowTextColorFormatting); MarkDirty(DirtMarkType.Value); }