canvas 的 .MoveUp 使用什么值

What value to use for .MoveUp of canvas

下面的代码将 PDF 文件中的所有页面复制到一个新文件,并在第一页的顶部插入一个带有红色边框的矩形,其中包含一段短文本。

如果我不移动它,顶部会留下一个空隙(这里放大了很多,字体大小只有8):

但是,如果我将矩形向上移动 4 的经验值:

    iText.Kernel.Geom.Rectangle pageSize = firstPage.GetCropBox().MoveUp(4);

顶部会有一个完美匹配:

值4与字体大小无关。

我不喜欢代码中的 幻数 所以,我的问题是:为什么是 4?什么表达式会揭示这个值 4?

代码行在此处的第一个方法中。第二个是使用它的地方,第三个是从第一个调用的;它只是提供一种风格:

private static void RegisterDocument(PdfDocument pdfDocument, string registration)
{
    // Magic value to close gap between top of page and top of rectangle with the registration.
    const float moveUp = 4F;

    Document document = new Document(pdfDocument, new PageSize(PageSize.A4));
    PdfPage firstPage = document.GetPdfDocument().GetFirstPage();

    Paragraph paragraph = new Paragraph(registration).AddStyle(RegistrationStyle());

    iText.Kernel.Geom.Rectangle pageSize = firstPage.GetCropBox().MoveUp(moveUp);
    LayoutContext layoutContext = new LayoutContext(new LayoutArea(1, pageSize));
    IRenderer renderer = paragraph.CreateRendererSubTree();
    renderer.SetParent(document.GetRenderer()).Layout(layoutContext);

    Canvas canvas = new Canvas(new PdfCanvas(firstPage, true), pageSize);
    canvas.Add(paragraph);          

    document.Close();   
}

public static void RegisterPdf(string sourceFilename, string targetFilename, string registration)
{
    if (registration.Length > 0)
    {
        // Open source and target PDF files.
        PdfDocument sourcePdf = new PdfDocument(new PdfReader(sourceFilename));
        PdfDocument targetPdf = new PdfDocument(new PdfWriter(targetFilename));

        // Copy all pages from source PDF to target PDF.
        sourcePdf.CopyPagesTo(1, sourcePdf.GetNumberOfPages(), targetPdf);

        // Add registration to page 1 of target and save the document.
        RegisterDocument(targetPdf, registration);

        // Close the files.
        sourcePdf.Close();
        targetPdf.Close();
    }
}

private static Style RegistrationStyle()
{
    // Fixed design values for font and rectangle.
    PdfFont font = PdfFontFactory.CreateFont(StandardFonts.HELVETICA);
    const float fontSize = 8F;
    const float rightPadding = 3F;
    TextAlignment textAlignment = TextAlignment.RIGHT;
    iText.Kernel.Colors.Color borderColor = ColorConstants.RED;
    iText.Kernel.Colors.Color fillColor = ColorConstants.WHITE;
    const float borderWidth = 0.7F;

    Style style = new Style()
        .SetFont(font)
        .SetFontSize(fontSize)
        .SetPaddingRight(rightPadding)
        .SetTextAlignment(textAlignment)
        .SetBackgroundColor(fillColor)
        .SetBorder(new SolidBorder(borderColor, borderWidth));

    return style;
}

如果不查看代码的所有细节,就无法判断。它可能取决于任意数量的情况和它们的组合。示例:

  • 您正在使用的 PDF 库中的默认值
  • 文档中定义的边距

你想知道

I dislike magic numbers in code so, my question is: Why 4? What expression would reveal this value of 4?

iText 在计算某个实体的布局时,会从多个来源检索属性,特别是实体本身及其渲染器。它不仅要求他们明确设置属性,还要求他们提供默认值。

在手头的案例中,您会看到 Paragraph class 的默认 top margin 值:

public override T1 GetDefaultProperty<T1>(int property) {
    switch (property) {
        case Property.LEADING: {
            return (T1)(Object)new Leading(Leading.MULTIPLIED, childElements.Count == 1 && childElements[0] is Image ? 
                1 : 1.35f);
        }

        case Property.FIRST_LINE_INDENT: {
            return (T1)(Object)0f;
        }

        case Property.MARGIN_TOP:
        case Property.MARGIN_BOTTOM: {
            return (T1)(Object)UnitValue.CreatePointValue(4f);
        }

        case Property.TAB_DEFAULT: {
            return (T1)(Object)50f;
        }

        default: {
            return base.GetDefaultProperty<T1>(property);
        }
    }
}

(iText 布局 Paragraph 方法)

如果将段落的上边距设置为 0,则可以大大简化代码:

public static void RegisterPdfImproved(string sourceFilename, string targetFilename, string registration)
{
    using (PdfDocument pdf = new PdfDocument(new PdfReader(sourceFilename), new PdfWriter(targetFilename)))
    using (Document document = new Document(pdf))
    {
        document.SetMargins(0, 0, 0, 0);
        Paragraph paragraph = new Paragraph(registration)
            .AddStyle(RegistrationStyle())
            .SetMarginTop(0);
        document.Add(paragraph);
    }
}

没有任何魔法值你现在得到