Где реализация InternalEquals (возразите objA, возразите objB),

easytable не поддерживает повторяющиеся верхние и нижние колонтитулы таблицы. Еще нет Я должен сказать, потому что эта функция на самом деле проста в реализации.

Тем не менее, трудно реализовать поверх easytable, потому что эта библиотека (как и многие другие) страдает от чрезмерного сокрытия данных: многие интересные переменные-члены и методы private, поэтому расширение классов не является жизнеспособным вариантом.

Но вы можете обрабатывать строки заголовков как отдельную таблицу, которую вы рисуете снова и снова! Недостатком является двойственность настроек.

В случае тестового кода TwoPagesTableTest, на который вы ссылались, его можно изменить следующим образом:

final Table.TableBuilder tableHeaderBuilder = Table.builder()
        .addColumnOfWidth(200)
        .addColumnOfWidth(200);

CellText dummyHeaderCell = CellText.builder()
        .text("Header dummy")
        .backgroundColor(Color.BLUE)
        .textColor(Color.WHITE)
        .borderWidth(1F)
        .build();

tableHeaderBuilder.addRow(
        Row.builder()
                .add(dummyHeaderCell)
                .add(dummyHeaderCell)
                .build());

Table tableHeader = tableHeaderBuilder.build();

final Table.TableBuilder tableBuilder = Table.builder()
        .addColumnOfWidth(200)
        .addColumnOfWidth(200);

CellText dummyCell = CellText.builder()
        .text("dummy")
        .borderWidth(1F)
        .build();

for (int i = 0; i < 50; i++) {
    tableBuilder.addRow(
            Row.builder()
                    .add(dummyCell)
                    .add(dummyCell)
                    .build());
}

TableDrawer drawer = TableDrawer.builder()
        .table(tableBuilder.build())
        .startX(50)
        .endY(50F) // note: if not set, table is drawn over the end of the page
        .build();

final PDDocument document = new PDDocument();

float startY = 100F;

do {
    TableDrawer headerDrawer = TableDrawer.builder()
            .table(tableHeader)
            .startX(50)
            .build();

    PDPage page = new PDPage(PDRectangle.A4);
    document.addPage(page);
    try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
        headerDrawer.startY(startY);
        headerDrawer.contentStream(contentStream).draw();
        drawer.startY(startY - tableHeader.getHeight());
        drawer.contentStream(contentStream).draw();
    }

    startY = page.getMediaBox().getHeight() - 50;
} while (!drawer.isFinished());

document.save("twoPageTable-repeatingHeader.pdf");
document.close();

( RepeatingTableHeaders test createTwoPageTableRepeatingHeader) [1110 ]

Как видите, код сначала создает отдельный Table tableHeader, содержащий только строку заголовка. Затем эта таблица добавляется первой на каждой странице, а затем добавляется часть таблицы строк тела.

Результат: заголовки таблиц на каждой странице ...

screen shot

Слово предупреждения: это подтверждение концепции, я проверял только код генерации таблицы из TwoPagesTableTest. Для производственного кода вы должны применить дальнейшие тесты.

5
задан Jonathan Leffler 3 May 2015 в 02:32
поделиться

1 ответ

Это объявляется как [MethodImpl(MethodImplOptions.InternalCall)]. Это означает, что это реализовано в самом CLR, как собственная процедура, не блок.NET.

Можно просмотреть подобный исходный код CLR путем рассмотрения Microsoft SSCLI (иначе Ротор).

В SSCLI 2.0 это реализовано как (в sscli20/clr/src/vm/comobject.cpp):

FCIMPL2(FC_BOOL_RET, ObjectNative::Equals, Object *pThisRef, Object *pCompareRef)
{
    CONTRACTL
    {
        THROWS;
        DISABLED(GC_NOTRIGGER);
        INJECT_FAULT(FCThrow(kOutOfMemoryException););
        MODE_COOPERATIVE;
        SO_TOLERANT;          
    }
    CONTRACTL_END;

    if (pThisRef == pCompareRef)    
        FC_RETURN_BOOL(TRUE);

    // Since we are in FCALL, we must handle NULL specially.
    if (pThisRef == NULL || pCompareRef == NULL)
         FC_RETURN_BOOL(FALSE);

    MethodTable *pThisMT = pThisRef->GetMethodTable();

    // If it's not a value class, don't compare by value
    if (!pThisMT->IsValueClass())
         FC_RETURN_BOOL(FALSE);

    // Make sure they are the same type.
    if (pThisMT != pCompareRef->GetMethodTable())
        FC_RETURN_BOOL(FALSE);

    // Compare the contents (size - vtable - sink block index).
    BOOL ret = memcmp(
        (void *) (pThisRef+1), 
        (void *) (pCompareRef+1), 
        pThisRef->GetMethodTable()->GetBaseSize() - sizeof(Object) - sizeof(int)) == 0;

    FC_GC_POLL_RET();

    FC_RETURN_BOOL(ret);
}
FCIMPLEND
12
ответ дан 13 December 2019 в 05:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: