示例#1
0
            public void WriteLineInfo(TextLayoutCommandStream output,
                                      Int32 lineWidth, Int32 lineHeight, Int32 lengthInCommands, Int32 lengthInGlyphs, Boolean terminatedByLineBreak, ref TextLayoutSettings settings)
            {
                var offset = 0;

                if (settings.Width.HasValue)
                {
                    if ((settings.Flags & TextFlags.AlignRight) == TextFlags.AlignRight)
                    {
                        offset = (settings.Width.Value - lineWidth);
                    }
                    else if ((settings.Flags & TextFlags.AlignCenter) == TextFlags.AlignCenter)
                    {
                        offset = (settings.Width.Value - lineWidth) / 2;
                    }
                }

                var outputStreamPosition = output.StreamPositionInObjects;

                output.Seek(lineInfoCommandIndex);
                unsafe
                {
                    var ptr = (TextLayoutLineInfoCommand *)output.Data;
                    ptr->Offset                = offset;
                    ptr->LineWidth             = lineWidth;
                    ptr->LineHeight            = lineHeight;
                    ptr->LengthInCommands      = lengthInCommands;
                    ptr->LengthInGlyphs        = lengthInGlyphs;
                    ptr->TerminatedByLineBreak = terminatedByLineBreak;
                }
                output.Seek(outputStreamPosition);

                minLineOffset = (minLineOffset.HasValue) ? Math.Min(minLineOffset.Value, offset) : offset;
            }
示例#2
0
            public void WriteBlockInfo(TextLayoutCommandStream output, Int32 blockWidth, Int32 blockHeight, Int32 lengthInLines, ref TextLayoutSettings settings)
            {
                var offset = 0;

                if (settings.Height.HasValue)
                {
                    if ((settings.Flags & TextFlags.AlignBottom) == TextFlags.AlignBottom)
                    {
                        offset = (settings.Height.Value - blockHeight);
                    }
                    else if ((settings.Flags & TextFlags.AlignMiddle) == TextFlags.AlignMiddle)
                    {
                        offset = (settings.Height.Value - blockHeight) / 2;
                    }
                }

                output.Seek(0);
                unsafe
                {
                    var ptr = (TextLayoutBlockInfoCommand *)output.Data;
                    ptr->Offset        = offset;
                    ptr->LengthInLines = lengthInLines;
                }
                output.Seek(output.Count);

                minBlockOffset = (minBlockOffset.HasValue) ? Math.Min(minBlockOffset.Value, offset) : offset;
            }
            public void WriteLineInfo(TextLayoutCommandStream output, 
                Int32 lineWidth, Int32 lineHeight, Int32 lengthInCommands, Int32 lengthInGlyphs, Boolean terminatedByLineBreak, ref TextLayoutSettings settings)
            {
                var offset = 0;

                if (settings.Width.HasValue)
                {
                    if ((settings.Flags & TextFlags.AlignRight) == TextFlags.AlignRight)
                        offset = (settings.Width.Value - lineWidth);
                    else if ((settings.Flags & TextFlags.AlignCenter) == TextFlags.AlignCenter)
                        offset = (settings.Width.Value - lineWidth) / 2;
                }

                var outputStreamPosition = output.StreamPositionInObjects;
                output.Seek(lineInfoCommandIndex);
                unsafe
                {
                    var ptr = (TextLayoutLineInfoCommand*)output.Data;
                    ptr->Offset = offset;
                    ptr->LineWidth = lineWidth;
                    ptr->LineHeight = lineHeight;
                    ptr->LengthInCommands = lengthInCommands;
                    ptr->LengthInGlyphs = lengthInGlyphs;
                    ptr->TerminatedByLineBreak = terminatedByLineBreak;
                }
                output.Seek(outputStreamPosition);

                minLineOffset = (minLineOffset.HasValue) ? Math.Min(minLineOffset.Value, offset) : offset;
            }
            public void WriteBlockInfo(TextLayoutCommandStream output, Int32 blockWidth, Int32 blockHeight, Int32 lengthInLines, ref TextLayoutSettings settings)
            {
                var offset = 0;

                if (settings.Height.HasValue)
                {
                    if ((settings.Flags & TextFlags.AlignBottom) == TextFlags.AlignBottom)
                        offset = (settings.Height.Value - blockHeight);
                    else if ((settings.Flags & TextFlags.AlignMiddle) == TextFlags.AlignMiddle)
                        offset = (settings.Height.Value - blockHeight) / 2;
                }

                output.Seek(0);
                unsafe
                {
                    var ptr = (TextLayoutBlockInfoCommand*)output.Data;
                    ptr->Offset = offset;
                    ptr->LengthInLines = lengthInLines;
                }
                output.Seek(output.Count);

                minBlockOffset = (minBlockOffset.HasValue) ? Math.Min(minBlockOffset.Value, offset) : offset;
            }
示例#5
0
            private unsafe void FixHorizontalAlignmentForUnconstrainedLayout(TextLayoutCommandStream output, ref TextLayoutSettings settings)
            {
                output.Seek(0);

                while (output.SeekNextLine())
                {
                    var lineInfo = (TextLayoutLineInfoCommand *)output.InternalObjectStream.Data;

                    if ((settings.Flags & TextFlags.AlignRight) == TextFlags.AlignRight)
                    {
                        lineInfo->Offset = (output.ActualWidth - lineInfo->LineWidth);
                    }
                    else if ((settings.Flags & TextFlags.AlignCenter) == TextFlags.AlignCenter)
                    {
                        lineInfo->Offset = (output.ActualWidth - lineInfo->LineWidth) / 2;
                    }
                }
            }
示例#6
0
            public unsafe Boolean ReplaceLastBreakingSpaceWithLineBreak(TextLayoutCommandStream output, ref TextLayoutSettings settings)
            {
                if (!lineBreakCommand.HasValue || !lineBreakOffset.HasValue)
                {
                    return(false);
                }

                var sizeBeforeBreak     = brokenTextSizeBeforeBreak.Value;
                var sizeAfterBreak      = brokenTextSizeAfterBreak.Value;
                var brokenCommandSize   = Size2.Zero;
                var brokenCommandOffset = 0;
                var brokenCommandLength = 0;

                var newLineHeight = sizeAfterBreak.Height;

                if (newLineHeight == 0)
                {
                    newLineHeight = settings.Font.GetFace(SpriteFontStyle.Regular).LineSpacing;
                }

                // Truncate the command which is being broken.
                output.Seek(lineBreakCommand.Value);
                unsafe
                {
                    var cmd = (TextLayoutTextCommand *)output.Data;

                    brokenCommandOffset = cmd->TextOffset;
                    brokenCommandLength = cmd->TextLength;
                    brokenCommandSize   = cmd->Bounds.Size;

                    cmd->TextLength = lineBreakOffset.Value;
                    cmd->TextWidth  = (Int16)sizeBeforeBreak.Width;
                    cmd->TextHeight = (Int16)sizeBeforeBreak.Height;
                }
                output.SeekNextCommand();

                // Insert a line break, a new line, and the second half of the truncated text.
                var part1Length          = lineBreakOffset.Value;
                var part2Offset          = brokenCommandOffset + (lineBreakOffset.Value + 1);
                var part2Length          = brokenCommandLength - (part1Length + 1);
                var part2IsNotDegenerate = (part2Length > 0);

                var numberOfObjects = part2IsNotDegenerate ? 3 : 2;
                var numberOfBytes   =
                    sizeof(TextLayoutLineBreakCommand) +
                    sizeof(TextLayoutLineInfoCommand) +
                    (part2IsNotDegenerate ? sizeof(TextLayoutTextCommand) : 0);

                var insertionPosition = output.InternalObjectStream.PositionInObjects;

                output.InternalObjectStream.ReserveInsert(numberOfObjects, numberOfBytes);

                *(TextLayoutLineBreakCommand *)output.Data = new TextLayoutLineBreakCommand(1);
                output.InternalObjectStream.FinalizeObject(sizeof(TextLayoutLineBreakCommand));

                *(TextLayoutCommandType *)output.Data = TextLayoutCommandType.LineInfo;
                output.InternalObjectStream.FinalizeObject(sizeof(TextLayoutLineInfoCommand));

                if (part2IsNotDegenerate)
                {
                    var textOffset = part2Offset;
                    var textLength = part2Length;

                    *(TextLayoutTextCommand *)output.InternalObjectStream.Data = new TextLayoutTextCommand(textOffset, textLength,
                                                                                                           0, positionY + lineHeight, (Int16)sizeAfterBreak.Width, (Int16)sizeAfterBreak.Height);
                    output.InternalObjectStream.FinalizeObject(sizeof(TextLayoutTextCommand));
                }

                // Add the line break command to the broken line.
                AdvanceLineToNextCommand(0, 0, 1, 1);

                // Recalculate the parameters for the broken line.
                output.Seek(LineInfoCommandIndex + 1);

                var brokenLineWidth            = 0;
                var brokenLineHeight           = 0;
                var brokenLineLengthInText     = 0;
                var brokenLineLengthInCommands = 0;

                var cmdType = TextLayoutCommandType.None;

                while ((cmdType = *(TextLayoutCommandType *)output.Data) != TextLayoutCommandType.LineInfo)
                {
                    switch (cmdType)
                    {
                    case TextLayoutCommandType.Text:
                    {
                        var cmd = (TextLayoutTextCommand *)output.Data;
                        brokenLineWidth        += cmd->TextWidth;
                        brokenLineHeight        = Math.Max(brokenLineHeight, cmd->TextHeight);
                        brokenLineLengthInText += cmd->TextLength;
                    }
                    break;

                    case TextLayoutCommandType.Icon:
                    {
                        var cmd = (TextLayoutIconCommand *)output.Data;
                        brokenLineWidth        += cmd->Bounds.Width;
                        brokenLineHeight        = Math.Max(brokenLineHeight, cmd->Bounds.Height);
                        brokenLineLengthInText += 1;
                    }
                    break;

                    case TextLayoutCommandType.LineBreak:
                    {
                        var cmd = (TextLayoutLineBreakCommand *)output.Data;
                        brokenLineLengthInText += cmd->Length;
                    }
                    break;
                    }
                    brokenLineLengthInCommands++;
                    output.SeekNextCommand();
                }

                // Finalize the broken line.
                totalLength          = (totalLength - lineLengthInText) + brokenLineLengthInText;
                lineWidth            = brokenLineWidth;
                lineHeight           = brokenLineHeight;
                lineLengthInText     = brokenLineLengthInText;
                lineLengthInCommands = brokenLineLengthInCommands;
                FinalizeLine(output, ref settings);

                // Fixup token bounds and update parameters for new line.
                LineInfoCommandIndex = insertionPosition + 1;
                while (output.StreamPositionInObjects < output.Count)
                {
                    var width            = 0;
                    var height           = 0;
                    var lengthInCommands = 0;
                    var lengthInText     = 0;

                    switch (*(TextLayoutCommandType *)output.Data)
                    {
                    case TextLayoutCommandType.Text:
                    {
                        var cmd = (TextLayoutTextCommand *)output.Data;
                        width            = cmd->TextWidth;
                        height           = cmd->TextHeight;
                        lengthInCommands = 1;
                        lengthInText     = cmd->TextLength;
                        cmd->TextX       = PositionX;
                        cmd->TextY       = PositionY;
                    }
                    break;

                    case TextLayoutCommandType.Icon:
                    {
                        var cmd = (TextLayoutIconCommand *)output.Data;
                        width            = cmd->IconWidth;
                        height           = cmd->IconHeight;
                        lengthInCommands = 1;
                        lengthInText     = 1;
                        cmd->IconX       = PositionX;
                        cmd->IconY       = PositionY;
                    }
                    break;

                    case TextLayoutCommandType.LineBreak:
                    {
                        var cmd = (TextLayoutLineBreakCommand *)output.Data;
                        lengthInText += cmd->Length;
                    }
                    break;
                    }

                    AdvanceLineToNextCommand(width, height, lengthInCommands, lengthInText);
                    output.SeekNextCommand();
                }

                return(true);
            }
            private unsafe void FixHorizontalAlignmentForUnconstrainedLayout(TextLayoutCommandStream output, ref TextLayoutSettings settings)
            {
                output.Seek(0);

                while (output.SeekNextLine())
                {
                    var lineInfo = (TextLayoutLineInfoCommand*)output.InternalObjectStream.Data;

                    if ((settings.Flags & TextFlags.AlignRight) == TextFlags.AlignRight)
                        lineInfo->Offset = (output.ActualWidth - lineInfo->LineWidth);
                    else if ((settings.Flags & TextFlags.AlignCenter) == TextFlags.AlignCenter)
                        lineInfo->Offset = (output.ActualWidth - lineInfo->LineWidth) / 2;
                }
            }
            public unsafe Boolean ReplaceLastBreakingSpaceWithLineBreak(TextLayoutCommandStream output, ref TextLayoutSettings settings)
            {
                if (!lineBreakCommand.HasValue || !lineBreakOffset.HasValue)
                    return false;

                var sizeBeforeBreak = brokenTextSizeBeforeBreak.Value;
                var sizeAfterBreak = brokenTextSizeAfterBreak.Value;
                var brokenCommandSize = Size2.Zero;
                var brokenCommandOffset = 0;
                var brokenCommandLength = 0;

                var newLineHeight = sizeAfterBreak.Height;
                if (newLineHeight == 0)
                    newLineHeight = settings.Font.GetFace(SpriteFontStyle.Regular).LineSpacing;

                // Truncate the command which is being broken.
                output.Seek(lineBreakCommand.Value);
                unsafe
                {
                    var cmd = (TextLayoutTextCommand*)output.Data;

                    brokenCommandOffset = cmd->TextOffset;
                    brokenCommandLength = cmd->TextLength;
                    brokenCommandSize = cmd->Bounds.Size;

                    cmd->TextLength = lineBreakOffset.Value;
                    cmd->TextWidth = (Int16)sizeBeforeBreak.Width;
                    cmd->TextHeight = (Int16)sizeBeforeBreak.Height;
                }
                output.SeekNextCommand();

                // Insert a line break, a new line, and the second half of the truncated text.
                var part1Length = lineBreakOffset.Value;
                var part2Offset = brokenCommandOffset + (lineBreakOffset.Value + 1);
                var part2Length = brokenCommandLength - (part1Length + 1);
                var part2IsNotDegenerate = (part2Length > 0);

                var numberOfObjects = part2IsNotDegenerate ? 3 : 2;
                var numberOfBytes =
                    sizeof(TextLayoutLineBreakCommand) +
                    sizeof(TextLayoutLineInfoCommand) +
                    (part2IsNotDegenerate ? sizeof(TextLayoutTextCommand) : 0);

                var insertionPosition = output.InternalObjectStream.PositionInObjects;

                output.InternalObjectStream.ReserveInsert(numberOfObjects, numberOfBytes);

                *(TextLayoutLineBreakCommand*)output.Data = new TextLayoutLineBreakCommand(1);
                output.InternalObjectStream.FinalizeObject(sizeof(TextLayoutLineBreakCommand));

                *(TextLayoutCommandType*)output.Data = TextLayoutCommandType.LineInfo;
                output.InternalObjectStream.FinalizeObject(sizeof(TextLayoutLineInfoCommand));

                if (part2IsNotDegenerate)
                {
                    var textOffset = part2Offset;
                    var textLength = part2Length;

                    *(TextLayoutTextCommand*)output.InternalObjectStream.Data = new TextLayoutTextCommand(textOffset, textLength,
                        0, positionY + lineHeight, (Int16)sizeAfterBreak.Width, (Int16)sizeAfterBreak.Height);
                    output.InternalObjectStream.FinalizeObject(sizeof(TextLayoutTextCommand));
                }

                // Add the line break command to the broken line.
                AdvanceLineToNextCommand(0, 0, 1, 1);

                // Recalculate the parameters for the broken line.
                output.Seek(LineInfoCommandIndex + 1);

                var brokenLineWidth = 0;
                var brokenLineHeight = 0;
                var brokenLineLengthInText = 0;
                var brokenLineLengthInCommands = 0;

                var cmdType = TextLayoutCommandType.None;
                while ((cmdType = *(TextLayoutCommandType*)output.Data) != TextLayoutCommandType.LineInfo)
                {
                    switch (cmdType)
                    {
                        case TextLayoutCommandType.Text:
                            {
                                var cmd = (TextLayoutTextCommand*)output.Data;
                                brokenLineWidth += cmd->TextWidth;
                                brokenLineHeight = Math.Max(brokenLineHeight, cmd->TextHeight);
                                brokenLineLengthInText += cmd->TextLength;
                            }
                            break;

                        case TextLayoutCommandType.Icon:
                            {
                                var cmd = (TextLayoutIconCommand*)output.Data;
                                brokenLineWidth += cmd->Bounds.Width;
                                brokenLineHeight = Math.Max(brokenLineHeight, cmd->Bounds.Height);
                                brokenLineLengthInText += 1;
                            }
                            break;

                        case TextLayoutCommandType.LineBreak:
                            {
                                var cmd = (TextLayoutLineBreakCommand*)output.Data;
                                brokenLineLengthInText += cmd->Length;
                            }
                            break;
                    }
                    brokenLineLengthInCommands++;
                    output.SeekNextCommand();
                }

                // Finalize the broken line.
                totalLength = (totalLength - lineLengthInText) + brokenLineLengthInText;
                lineWidth = brokenLineWidth;
                lineHeight = brokenLineHeight;
                lineLengthInText = brokenLineLengthInText;
                lineLengthInCommands = brokenLineLengthInCommands;
                FinalizeLine(output, ref settings);

                // Fixup token bounds and update parameters for new line.
                LineInfoCommandIndex = insertionPosition + 1;
                while (output.StreamPositionInObjects < output.Count)
                {
                    var width = 0;
                    var height = 0;
                    var lengthInCommands = 0;
                    var lengthInText = 0;

                    switch (*(TextLayoutCommandType*)output.Data)
                    {
                        case TextLayoutCommandType.Text:
                            {
                                var cmd = (TextLayoutTextCommand*)output.Data;
                                width = cmd->TextWidth;
                                height = cmd->TextHeight;
                                lengthInCommands = 1;
                                lengthInText = cmd->TextLength;
                                cmd->TextX = PositionX;
                                cmd->TextY = PositionY;
                            }
                            break;

                        case TextLayoutCommandType.Icon:
                            {
                                var cmd = (TextLayoutIconCommand*)output.Data;
                                width = cmd->IconWidth;
                                height = cmd->IconHeight;
                                lengthInCommands = 1;
                                lengthInText = 1;
                                cmd->IconX = PositionX;
                                cmd->IconY = PositionY;
                            }
                            break;

                        case TextLayoutCommandType.LineBreak:
                            {
                                var cmd = (TextLayoutLineBreakCommand*)output.Data;
                                lengthInText += cmd->Length;
                            }
                            break;
                    }

                    AdvanceLineToNextCommand(width, height, lengthInCommands, lengthInText);
                    output.SeekNextCommand();
                }

                return true;
            }