Ejemplo n.º 1
0
        //GetHeadTailBreak 根据行首、尾对字符的约束条件,获取截断位置
        private void GetHeadTailBreak(string aText, ref int aPos)
        {
            if (aPos < 1)
            {
                return;
            }

            Char vChar = aText[aPos + 1 - 1];                  // 因为是要处理截断,所以APos肯定是小于Length(AText)的,不用考虑越界

            if (HC.PosCharHC(vChar, HC.DontLineFirstChar) > 0) // 下一个是不能放在行首的字符
            {
                aPos--;                                        // 当前要移动到下一行,往前一个截断重新判断
                GetHeadTailBreak(aText, ref aPos);
            }
            else  // 下一个可以放在行首,当前位置能否放置到行尾
            {
                vChar = aText[aPos - 1];  // 当前位置字符
                if (HC.PosCharHC(vChar, HC.DontLineLastChar) > 0) // 是不能放在行尾的字符
                {
                    aPos--;                                       // 再往前寻找截断位置
                    GetHeadTailBreak(aText, ref aPos);
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary> 从指定偏移和指定位置开始格式化Text </summary>
        /// <param name="aCharOffset">文本格式化的起始偏移</param>
        /// <param name="aPlaceWidth">呈放文本的宽度</param>
        /// <param name="aBasePos">vCharWidths中对应偏移的起始位置</param>
        private void DoFormatTextItemToDrawItems(HCCustomItem vItem, int aOffset, string vText, int aCharOffset, int aPlaceWidth, int aBasePos,
                                                 int aItemNo, int vItemLen, int aFmtLeft, int aContentWidth, int aFmtRight,
                                                 int[] vCharWidths, ref bool vParaFirst, ref bool vLineFirst, ref POINT aPos, ref RECT vRect,
                                                 ref int vRemainderWidth, ref int aLastDrawItemNo)
        {
            int viPlaceOffset,   // 能放下第几个字符
                viBreakOffset,   // 第几个字符放不下
                vFirstCharWidth; // 第一个字符的宽度

            vLineFirst      = vParaFirst || ((aPos.X == aFmtLeft) && (DrawItems[aLastDrawItemNo].Width != 0));
            viBreakOffset   = 0;                                       // 换行位置,第几个字符放不下
            vFirstCharWidth = vCharWidths[aCharOffset - 1] - aBasePos; // 第一个字符的宽度

            if (aPlaceWidth < 0)
            {
                viBreakOffset = 1;
            }
            else
            {
                for (int i = aCharOffset - 1; i <= vItemLen - 1; i++)
                {
                    if (vCharWidths[i] - aBasePos > aPlaceWidth)
                    {
                        viBreakOffset = i + 1;
                        break;
                    }
                }
            }

            if (viBreakOffset < 1)  // 当前行剩余空间把vText全放置下了
            {
                vRect.Left   = aPos.X;
                vRect.Top    = aPos.Y;
                vRect.Right  = vRect.Left + vCharWidths[vItemLen - 1] - aBasePos; // 使用自定义测量的结果
                vRect.Bottom = vRect.Top + FItemFormatHeight;
                NewDrawItem(aItemNo, aOffset + aCharOffset - 1, vItemLen - aCharOffset + 1, vRect, vParaFirst, vLineFirst, ref aLastDrawItemNo);
                vParaFirst = false;

                vRemainderWidth = aFmtRight - vRect.Right;  // 放入最多后的剩余量
            }
            else
            if (viBreakOffset == 1)                         // 当前行剩余空间连第一个字符也放不下
            {
                if (vFirstCharWidth > aFmtRight - aFmtLeft) // Data的宽度不足一个字符
                {
                    vRect.Left   = aPos.X;
                    vRect.Top    = aPos.Y;
                    vRect.Right  = vRect.Left + vCharWidths[vItemLen - 1] - aBasePos; // 使用自定义测量的结果
                    vRect.Bottom = vRect.Top + FItemFormatHeight;
                    NewDrawItem(aItemNo, aOffset + aCharOffset - 1, 1, vRect, vParaFirst, vLineFirst, ref aLastDrawItemNo);
                    vParaFirst = false;

                    vRemainderWidth = aFmtRight - vRect.Right;  // 放入最多后的剩余量
                    FinishLine(aItemNo, aLastDrawItemNo, vRemainderWidth);

                    // 偏移到下一行顶端,准备另起一行
                    aPos.X = aFmtLeft;
                    aPos.Y = DrawItems[aLastDrawItemNo].Rect.Bottom;  // 不使用 vRect.Bottom 因为如果行中间有高的,会修正vRect.Bottom

                    if (aCharOffset < vItemLen)
                    {
                        DoFormatTextItemToDrawItems(vItem, aOffset, vText, aCharOffset + 1, aFmtRight - aPos.X, vCharWidths[aCharOffset - 1],
                                                    aItemNo, vItemLen, aFmtLeft, aContentWidth, aFmtRight, vCharWidths,
                                                    ref vParaFirst, ref vLineFirst, ref aPos, ref vRect, ref vRemainderWidth, ref aLastDrawItemNo);
                    }
                }
                else  // Data的宽度足够一个字符
                if ((HC.PosCharHC(vText[aCharOffset - 1], HC.DontLineFirstChar) > 0) &&
                    (Items[aItemNo - 1].StyleNo > HCStyle.Null) &&
                    (DrawItems[aLastDrawItemNo].CharLen > 1))
                {
                    _FormatBreakTextDrawItem(aItemNo, aFmtLeft, aFmtRight, ref aLastDrawItemNo, ref aPos, ref vRect, ref vRemainderWidth, ref vParaFirst);      // 上一个重新分裂
                    CalcItemFormatHeigh(vItem);

                    DoFormatTextItemToDrawItems(vItem, aOffset, vText, aCharOffset, aFmtRight - aPos.X, aBasePos, aItemNo, vItemLen, aFmtLeft, aContentWidth,
                                                aFmtRight, vCharWidths, ref vParaFirst, ref vLineFirst, ref aPos, ref vRect, ref vRemainderWidth, ref aLastDrawItemNo);
                }
                else      // 整体下移到下一行
                {
                    vRemainderWidth = aPlaceWidth;
                    FinishLine(aItemNo, aLastDrawItemNo, vRemainderWidth);
                    // 偏移到下一行开始计算
                    aPos.X = aFmtLeft;
                    aPos.Y = DrawItems[aLastDrawItemNo].Rect.Bottom;
                    DoFormatTextItemToDrawItems(vItem, aOffset, vText, aCharOffset, aFmtRight - aPos.X, aBasePos,
                                                aItemNo, vItemLen, aFmtLeft, aContentWidth, aFmtRight, vCharWidths,
                                                ref vParaFirst, ref vLineFirst, ref aPos, ref vRect, ref vRemainderWidth, ref aLastDrawItemNo);
                }
            }
            else  // 当前行剩余宽度能放下当前Text的一部分
            {
                if (vFirstCharWidth > aFmtRight - aFmtLeft)  // Data的宽度不足一个字符
                {
                    viPlaceOffset = viBreakOffset;
                }
                else
                {
                    viPlaceOffset = viBreakOffset - 1;                // 第viBreakOffset个字符放不下,前一个能放下
                }
                FindLineBreak(vText, aCharOffset, ref viPlaceOffset); // 判断从viPlaceOffset后打断是否合适

                if ((viPlaceOffset == 0) && (!vLineFirst))            // 能放下的都不合适放到当前行且不是行首格式化,整体下移
                {
                    vRemainderWidth = aPlaceWidth;
                    FinishLine(aItemNo, aLastDrawItemNo, vRemainderWidth);
                    aPos.X = aFmtLeft;  // 偏移到下一行开始计算
                    aPos.Y = DrawItems[aLastDrawItemNo].Rect.Bottom;
                    DoFormatTextItemToDrawItems(vItem, aOffset, vText, aCharOffset, aFmtRight - aPos.X, aBasePos, aItemNo, vItemLen,
                                                aFmtLeft, aContentWidth, aFmtRight, vCharWidths, ref vParaFirst, ref vLineFirst, ref aPos, ref vRect, ref vRemainderWidth, ref aLastDrawItemNo);
                }
                else  // 有适合放到当前行的内容
                {
                    if (viPlaceOffset < aCharOffset)  // 找不到截断位置,就在原位置截断(如整行文本都是逗号)
                    {
                        if (vFirstCharWidth > aFmtRight - aFmtLeft)  // Data的宽度不足一个字符
                        {
                            viPlaceOffset = viBreakOffset;
                        }
                        else
                        {
                            viPlaceOffset = viBreakOffset - 1;
                        }
                    }

                    vRect.Left   = aPos.X;
                    vRect.Top    = aPos.Y;
                    vRect.Right  = vRect.Left + vCharWidths[viPlaceOffset - 1] - aBasePos; // 使用自定义测量的结果
                    vRect.Bottom = vRect.Top + FItemFormatHeight;

                    NewDrawItem(aItemNo, aOffset + aCharOffset - 1, viPlaceOffset - aCharOffset + 1, vRect, vParaFirst, vLineFirst, ref aLastDrawItemNo);
                    vParaFirst = false;

                    vRemainderWidth = aFmtRight - vRect.Right;  // 放入最多后的剩余量

                    FinishLine(aItemNo, aLastDrawItemNo, vRemainderWidth);

                    // 偏移到下一行顶端,准备另起一行
                    aPos.X = aFmtLeft;
                    aPos.Y = DrawItems[aLastDrawItemNo].Rect.Bottom;  // 不使用 vRect.Bottom 因为如果行中间有高的,会修正vRect.Bottom

                    if (viPlaceOffset < vItemLen)
                    {
                        DoFormatTextItemToDrawItems(vItem, aOffset, vText, viPlaceOffset + 1, aFmtRight - aPos.X, vCharWidths[viPlaceOffset - 1],
                                                    aItemNo, vItemLen, aFmtLeft, aContentWidth, aFmtRight, vCharWidths, ref vParaFirst, ref vLineFirst, ref aPos,
                                                    ref vRect, ref vRemainderWidth, ref aLastDrawItemNo);
                    }
                }
            }
        }