/// <summary> /// Calculates a layout for the specified text. /// </summary> /// <param name="input">The parsed text which will be laid out according to the specified settings.</param> /// <param name="output">The layout command stream which will be populated with commands by this operation.</param> /// <param name="settings">A <see cref="TextLayoutSettings"/> structure which contains the settings for this operation.</param> public void CalculateLayout(TextParserTokenStream input, TextLayoutCommandStream output, TextLayoutSettings settings) { Contract.Require(input, nameof(input)); Contract.Require(output, nameof(output)); if (settings.Font == null) { throw new ArgumentException(UltravioletStrings.InvalidLayoutSettings); } var state = new LayoutState() { LineInfoCommandIndex = 1 }; output.Clear(); output.SourceText = input.SourceText; output.ParserOptions = input.ParserOptions; var acquiredPointers = !output.HasAcquiredPointers; if (acquiredPointers) { output.AcquirePointers(); } output.WriteBlockInfo(); output.WriteLineInfo(); var bold = (settings.Style == SpriteFontStyle.Bold || settings.Style == SpriteFontStyle.BoldItalic); var italic = (settings.Style == SpriteFontStyle.Italic || settings.Style == SpriteFontStyle.BoldItalic); if (settings.InitialLayoutStyle != null) { PrepareInitialStyle(output, ref bold, ref italic, ref settings); } var currentFont = settings.Font; var currentFontFace = settings.Font.GetFace(SpriteFontStyle.Regular); var index = 0; var processing = true; while (index < input.Count && processing) { if (state.PositionY >= (settings.Height ?? Int32.MaxValue)) { break; } var token = input[index]; currentFontFace = default(SpriteFontFace); currentFont = GetCurrentFont(ref settings, bold, italic, out currentFontFace); switch (token.TokenType) { case TextParserTokenType.Text: processing = ProcessTextToken(input, output, currentFontFace, ref token, ref state, ref settings, ref index); break; case TextParserTokenType.Icon: processing = ProcessIconToken(output, ref token, ref state, ref settings, ref index); break; case TextParserTokenType.ToggleBold: ProcessToggleBoldToken(output, ref bold, ref state, ref index); break; case TextParserTokenType.ToggleItalic: ProcessToggleItalicToken(output, ref italic, ref state, ref index); break; case TextParserTokenType.PushFont: ProcessPushFontToken(output, ref token, ref state, ref index); break; case TextParserTokenType.PushColor: ProcessPushColorToken(output, ref token, ref state, ref index); break; case TextParserTokenType.PushStyle: ProcessPushStyleToken(output, ref bold, ref italic, ref token, ref state, ref index); break; case TextParserTokenType.PushGlyphShader: ProcessPushGlyphShaderToken(output, ref token, ref state, ref index); break; case TextParserTokenType.PushLink: ProcessPushLinkToken(output, ref token, ref state, ref index); break; case TextParserTokenType.PopFont: ProcessPopFontToken(output, ref token, ref state, ref index); break; case TextParserTokenType.PopColor: ProcessPopColorToken(output, ref token, ref state, ref index); break; case TextParserTokenType.PopStyle: ProcessPopStyleToken(output, ref bold, ref italic, ref token, ref state, ref index); break; case TextParserTokenType.PopGlyphShader: ProcessPopGlyphShaderToken(output, ref token, ref state, ref index); break; case TextParserTokenType.PopLink: ProcessPopLinkToken(output, ref token, ref state, ref index); break; default: if (token.TokenType >= TextParserTokenType.Custom) { ProcessCustomCommandToken(output, ref token, ref state, ref index); break; } else { throw new InvalidOperationException(UltravioletStrings.UnrecognizedLayoutCommand.Format(token.TokenType)); } } } state.FinalizeLayout(output, ref settings); if (acquiredPointers) { output.ReleasePointers(); } ClearLayoutStacks(); }
/// <summary> /// Advances the layout state to the next line of text. /// </summary> /// <param name="output">The <see cref="TextLayoutCommandStream"/> which is being populated.</param> /// <param name="settings">The current layout settings.</param> public void AdvanceLayoutToNextLine(TextLayoutCommandStream output, ref TextLayoutSettings settings) { FinalizeLine(output, ref settings); output.WriteLineInfo(); }
/// <summary> /// Calculates a layout for the specified text. /// </summary> /// <param name="input">The parsed text which will be laid out according to the specified settings.</param> /// <param name="output">The layout command stream which will be populated with commands by this operation.</param> /// <param name="settings">A <see cref="TextLayoutSettings"/> structure which contains the settings for this operation.</param> public void CalculateLayout(TextParserTokenStream input, TextLayoutCommandStream output, TextLayoutSettings settings) { Contract.Require(input, "input"); Contract.Require(output, "output"); if (settings.Font == null) throw new ArgumentException(UltravioletStrings.InvalidLayoutSettings); var state = new LayoutState() { LineInfoCommandIndex = 1 }; output.Clear(); output.SourceText = input.SourceText; output.ParserOptions = input.ParserOptions; var acquiredPointers = !output.HasAcquiredPointers; if (acquiredPointers) output.AcquirePointers(); output.WriteBlockInfo(); output.WriteLineInfo(); var bold = (settings.Style == SpriteFontStyle.Bold || settings.Style == SpriteFontStyle.BoldItalic); var italic = (settings.Style == SpriteFontStyle.Italic || settings.Style == SpriteFontStyle.BoldItalic); if (settings.InitialLayoutStyle != null) PrepareInitialStyle(output, ref bold, ref italic, ref settings); var currentFont = settings.Font; var currentFontFace = settings.Font.GetFace(SpriteFontStyle.Regular); var index = 0; var processing = true; while (index < input.Count && processing) { if (state.PositionY >= (settings.Height ?? Int32.MaxValue)) break; var token = input[index]; currentFontFace = default(SpriteFontFace); currentFont = GetCurrentFont(ref settings, bold, italic, out currentFontFace); switch (token.TokenType) { case TextParserTokenType.Text: processing = ProcessTextToken(input, output, currentFontFace, ref token, ref state, ref settings, ref index); break; case TextParserTokenType.Icon: processing = ProcessIconToken(output, ref token, ref state, ref settings, ref index); break; case TextParserTokenType.ToggleBold: ProcessToggleBoldToken(output, ref bold, ref state, ref index); break; case TextParserTokenType.ToggleItalic: ProcessToggleItalicToken(output, ref italic, ref state, ref index); break; case TextParserTokenType.PushFont: ProcessPushFontToken(output, ref token, ref state, ref index); break; case TextParserTokenType.PushColor: ProcessPushColorToken(output, ref token, ref state, ref index); break; case TextParserTokenType.PushStyle: ProcessPushStyleToken(output, ref bold, ref italic, ref token, ref state, ref index); break; case TextParserTokenType.PushGlyphShader: ProcessPushGlyphShaderToken(output, ref token, ref state, ref index); break; case TextParserTokenType.PopFont: ProcessPopFontToken(output, ref token, ref state, ref index); break; case TextParserTokenType.PopColor: ProcessPopColorToken(output, ref token, ref state, ref index); break; case TextParserTokenType.PopStyle: ProcessPopStyleToken(output, ref bold, ref italic, ref token, ref state, ref index); break; case TextParserTokenType.PopGlyphShader: ProcessPopGlyphShaderToken(output, ref token, ref state, ref index); break; default: throw new InvalidOperationException(UltravioletStrings.UnrecognizedLayoutCommand.Format(token.TokenType)); } } state.FinalizeLayout(output, ref settings); if (acquiredPointers) output.ReleasePointers(); ClearLayoutStacks(); }