From 618edef2dfea870c34800dbf3f2fd3f7be819300 Mon Sep 17 00:00:00 2001 From: xlou Date: Fri, 12 Oct 2018 23:37:41 +0000 Subject: Add setters/getters for BleedBox and TrimBox. Since BleedBox and TrimBox are supported according to PDF specification, hence added setters and getters to get the value if exists. Bug:894655 Change-Id: I3c2600450f07665241a4724457a7cbc4282941ed Reviewed-on: https://pdfium-review.googlesource.com/c/43977 Commit-Queue: Shirleen Lou Reviewed-by: Lei Zhang --- constants/page_object.h | 2 + fpdfsdk/fpdf_transformpage.cpp | 38 +++++ fpdfsdk/fpdf_transformpage_embeddertest.cpp | 244 +++++++++++++++++----------- fpdfsdk/fpdf_view_c_api_test.c | 4 + public/fpdf_transformpage.h | 66 ++++++++ testing/resources/cropped_text.in | 8 + testing/resources/cropped_text.pdf | 16 +- 7 files changed, 275 insertions(+), 103 deletions(-) diff --git a/constants/page_object.h b/constants/page_object.h index b7f927b56f..8a41b8cf5d 100644 --- a/constants/page_object.h +++ b/constants/page_object.h @@ -16,6 +16,8 @@ constexpr char kParent[] = "Parent"; constexpr char kResources[] = "Resources"; constexpr char kMediaBox[] = "MediaBox"; constexpr char kCropBox[] = "CropBox"; +constexpr char kBleedBox[] = "BleedBox"; +constexpr char kTrimBox[] = "TrimBox"; constexpr char kArtBox[] = "ArtBox"; constexpr char kContents[] = "Contents"; constexpr char kRotate[] = "Rotate"; diff --git a/fpdfsdk/fpdf_transformpage.cpp b/fpdfsdk/fpdf_transformpage.cpp index 7595086c87..8e8c9d5b70 100644 --- a/fpdfsdk/fpdf_transformpage.cpp +++ b/fpdfsdk/fpdf_transformpage.cpp @@ -80,6 +80,24 @@ FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetCropBox(FPDF_PAGE page, CFX_FloatRect(left, bottom, right, top)); } +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetBleedBox(FPDF_PAGE page, + float left, + float bottom, + float right, + float top) { + SetBoundingBox(CPDFPageFromFPDFPage(page), pdfium::page_object::kBleedBox, + CFX_FloatRect(left, bottom, right, top)); +} + +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetTrimBox(FPDF_PAGE page, + float left, + float bottom, + float right, + float top) { + SetBoundingBox(CPDFPageFromFPDFPage(page), pdfium::page_object::kTrimBox, + CFX_FloatRect(left, bottom, right, top)); +} + FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetArtBox(FPDF_PAGE page, float left, float bottom, @@ -109,6 +127,26 @@ FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetCropBox(FPDF_PAGE page, top); } +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetBleedBox(FPDF_PAGE page, + float* left, + float* bottom, + float* right, + float* top) { + return GetBoundingBox(CPDFPageFromFPDFPage(page), + pdfium::page_object::kBleedBox, left, bottom, right, + top); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetTrimBox(FPDF_PAGE page, + float* left, + float* bottom, + float* right, + float* top) { + return GetBoundingBox(CPDFPageFromFPDFPage(page), + pdfium::page_object::kTrimBox, left, bottom, right, + top); +} + FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetArtBox(FPDF_PAGE page, float* left, float* bottom, diff --git a/fpdfsdk/fpdf_transformpage_embeddertest.cpp b/fpdfsdk/fpdf_transformpage_embeddertest.cpp index 3904b0c321..8fa33704c7 100644 --- a/fpdfsdk/fpdf_transformpage_embeddertest.cpp +++ b/fpdfsdk/fpdf_transformpage_embeddertest.cpp @@ -15,38 +15,45 @@ TEST_F(FPDFTransformEmbedderTest, GetBoundingBoxes) { FPDF_PAGE page = LoadPage(1); ASSERT_TRUE(page); - float mediabox_left; - float mediabox_bottom; - float mediabox_right; - float mediabox_top; - EXPECT_TRUE(FPDFPage_GetMediaBox(page, &mediabox_left, &mediabox_bottom, - &mediabox_right, &mediabox_top)); - EXPECT_EQ(-50, mediabox_left); - EXPECT_EQ(-50, mediabox_bottom); - EXPECT_EQ(200, mediabox_right); - EXPECT_EQ(200, mediabox_top); - - float cropbox_left; - float cropbox_bottom; - float cropbox_right; - float cropbox_top; - EXPECT_TRUE(FPDFPage_GetCropBox(page, &cropbox_left, &cropbox_bottom, - &cropbox_right, &cropbox_top)); - EXPECT_EQ(50, cropbox_left); - EXPECT_EQ(50, cropbox_bottom); - EXPECT_EQ(150, cropbox_right); - EXPECT_EQ(150, cropbox_top); - - float artbox_left; - float artbox_bottom; - float artbox_right; - float artbox_top; - EXPECT_TRUE(FPDFPage_GetArtBox(page, &artbox_left, &artbox_bottom, - &artbox_right, &artbox_top)); - EXPECT_EQ(50, artbox_left); - EXPECT_EQ(60, artbox_bottom); - EXPECT_EQ(135, artbox_right); - EXPECT_EQ(140, artbox_top); + FS_RECTF mediabox; + EXPECT_TRUE(FPDFPage_GetMediaBox(page, &mediabox.left, &mediabox.bottom, + &mediabox.right, &mediabox.top)); + EXPECT_EQ(-50, mediabox.left); + EXPECT_EQ(-50, mediabox.bottom); + EXPECT_EQ(200, mediabox.right); + EXPECT_EQ(200, mediabox.top); + + FS_RECTF cropbox; + EXPECT_TRUE(FPDFPage_GetCropBox(page, &cropbox.left, &cropbox.bottom, + &cropbox.right, &cropbox.top)); + EXPECT_EQ(50, cropbox.left); + EXPECT_EQ(50, cropbox.bottom); + EXPECT_EQ(150, cropbox.right); + EXPECT_EQ(150, cropbox.top); + + FS_RECTF bleedbox; + EXPECT_TRUE(FPDFPage_GetBleedBox(page, &bleedbox.left, &bleedbox.bottom, + &bleedbox.right, &bleedbox.top)); + EXPECT_EQ(0, bleedbox.left); + EXPECT_EQ(10, bleedbox.bottom); + EXPECT_EQ(150, bleedbox.right); + EXPECT_EQ(145, bleedbox.top); + + FS_RECTF trimbox; + EXPECT_TRUE(FPDFPage_GetTrimBox(page, &trimbox.left, &trimbox.bottom, + &trimbox.right, &trimbox.top)); + EXPECT_EQ(25, trimbox.left); + EXPECT_EQ(30, trimbox.bottom); + EXPECT_EQ(140, trimbox.right); + EXPECT_EQ(145, trimbox.top); + + FS_RECTF artbox; + EXPECT_TRUE(FPDFPage_GetArtBox(page, &artbox.left, &artbox.bottom, + &artbox.right, &artbox.top)); + EXPECT_EQ(50, artbox.left); + EXPECT_EQ(60, artbox.bottom); + EXPECT_EQ(135, artbox.right); + EXPECT_EQ(140, artbox.top); UnloadPage(page); } @@ -55,48 +62,55 @@ TEST_F(FPDFTransformEmbedderTest, GetBoundingBoxes) { FPDF_PAGE page = LoadPage(3); ASSERT_TRUE(page); - float mediabox_left; - float mediabox_bottom; - float mediabox_right; - float mediabox_top; - EXPECT_TRUE(FPDFPage_GetMediaBox(page, &mediabox_left, &mediabox_bottom, - &mediabox_right, &mediabox_top)); - EXPECT_EQ(0, mediabox_left); - EXPECT_EQ(0, mediabox_bottom); - EXPECT_EQ(200, mediabox_right); - EXPECT_EQ(200, mediabox_top); - - float cropbox_left; - float cropbox_bottom; - float cropbox_right; - float cropbox_top; - EXPECT_TRUE(FPDFPage_GetCropBox(page, &cropbox_left, &cropbox_bottom, - &cropbox_right, &cropbox_top)); - EXPECT_EQ(150, cropbox_left); - EXPECT_EQ(150, cropbox_bottom); - EXPECT_EQ(60, cropbox_right); - EXPECT_EQ(60, cropbox_top); - - EXPECT_FALSE(FPDFPage_GetCropBox(page, nullptr, &cropbox_bottom, - &cropbox_right, &cropbox_top)); - EXPECT_FALSE(FPDFPage_GetCropBox(page, &cropbox_left, nullptr, - &cropbox_right, &cropbox_top)); - EXPECT_FALSE(FPDFPage_GetCropBox(page, &cropbox_left, &cropbox_bottom, - nullptr, &cropbox_top)); - EXPECT_FALSE(FPDFPage_GetCropBox(page, &cropbox_left, &cropbox_bottom, - &cropbox_right, nullptr)); + FS_RECTF mediabox; + EXPECT_TRUE(FPDFPage_GetMediaBox(page, &mediabox.left, &mediabox.bottom, + &mediabox.right, &mediabox.top)); + EXPECT_EQ(0, mediabox.left); + EXPECT_EQ(0, mediabox.bottom); + EXPECT_EQ(200, mediabox.right); + EXPECT_EQ(200, mediabox.top); + + FS_RECTF cropbox; + EXPECT_TRUE(FPDFPage_GetCropBox(page, &cropbox.left, &cropbox.bottom, + &cropbox.right, &cropbox.top)); + EXPECT_EQ(150, cropbox.left); + EXPECT_EQ(150, cropbox.bottom); + EXPECT_EQ(60, cropbox.right); + EXPECT_EQ(60, cropbox.top); + + EXPECT_FALSE(FPDFPage_GetCropBox(page, nullptr, &cropbox.bottom, + &cropbox.right, &cropbox.top)); + EXPECT_FALSE(FPDFPage_GetCropBox(page, &cropbox.left, nullptr, + &cropbox.right, &cropbox.top)); + EXPECT_FALSE(FPDFPage_GetCropBox(page, &cropbox.left, &cropbox.bottom, + nullptr, &cropbox.top)); + EXPECT_FALSE(FPDFPage_GetCropBox(page, &cropbox.left, &cropbox.bottom, + &cropbox.right, nullptr)); EXPECT_FALSE(FPDFPage_GetCropBox(page, nullptr, nullptr, nullptr, nullptr)); - float artbox_left; - float artbox_bottom; - float artbox_right; - float artbox_top; - EXPECT_TRUE(FPDFPage_GetArtBox(page, &artbox_left, &artbox_bottom, - &artbox_right, &artbox_top)); - EXPECT_EQ(140, artbox_left); - EXPECT_EQ(145, artbox_bottom); - EXPECT_EQ(65, artbox_right); - EXPECT_EQ(70, artbox_top); + FS_RECTF bleedbox; + EXPECT_TRUE(FPDFPage_GetBleedBox(page, &bleedbox.left, &bleedbox.bottom, + &bleedbox.right, &bleedbox.top)); + EXPECT_EQ(160, bleedbox.left); + EXPECT_EQ(165, bleedbox.bottom); + EXPECT_EQ(0, bleedbox.right); + EXPECT_EQ(10, bleedbox.top); + + FS_RECTF trimbox; + EXPECT_TRUE(FPDFPage_GetTrimBox(page, &trimbox.left, &trimbox.bottom, + &trimbox.right, &trimbox.top)); + EXPECT_EQ(155, trimbox.left); + EXPECT_EQ(165, trimbox.bottom); + EXPECT_EQ(25, trimbox.right); + EXPECT_EQ(30, trimbox.top); + + FS_RECTF artbox; + EXPECT_TRUE(FPDFPage_GetArtBox(page, &artbox.left, &artbox.bottom, + &artbox.right, &artbox.top)); + EXPECT_EQ(140, artbox.left); + EXPECT_EQ(145, artbox.bottom); + EXPECT_EQ(65, artbox.right); + EXPECT_EQ(70, artbox.top); UnloadPage(page); } @@ -109,37 +123,50 @@ TEST_F(FPDFTransformEmbedderTest, NoCropBox) { FPDF_PAGE page = LoadPage(0); ASSERT_TRUE(page); - float left = -1.0f; - float bottom = -2.0f; - float right = 3.0f; - float top = 0.0f; - EXPECT_FALSE(FPDFPage_GetCropBox(page, &left, &bottom, &right, &top)); - EXPECT_EQ(-1.0f, left); - EXPECT_EQ(-2.0f, bottom); - EXPECT_EQ(3.0f, right); - EXPECT_EQ(0.0f, top); + FS_RECTF cropbox = {-1.0f, 0.0f, 3.0f, -2.0f}; + EXPECT_FALSE(FPDFPage_GetCropBox(page, &cropbox.left, &cropbox.bottom, + &cropbox.right, &cropbox.top)); + EXPECT_EQ(-1.0f, cropbox.left); + EXPECT_EQ(-2.0f, cropbox.bottom); + EXPECT_EQ(3.0f, cropbox.right); + EXPECT_EQ(0.0f, cropbox.top); UnloadPage(page); } -TEST_F(FPDFTransformEmbedderTest, ClipPath) { +TEST_F(FPDFTransformEmbedderTest, NoBleedBox) { ASSERT_TRUE(OpenDocument("hello_world.pdf")); + ASSERT_EQ(1, FPDF_GetPageCount(document())); FPDF_PAGE page = LoadPage(0); ASSERT_TRUE(page); - FPDF_CLIPPATH clip = FPDF_CreateClipPath(10.0f, 10.0f, 90.0f, 90.0f); - EXPECT_TRUE(clip); + FS_RECTF bleedbox = {-1.0f, 10.f, 3.0f, -1.0f}; + EXPECT_FALSE(FPDFPage_GetBleedBox(page, &bleedbox.left, &bleedbox.bottom, + &bleedbox.right, &bleedbox.top)); + EXPECT_EQ(-1.0f, bleedbox.left); + EXPECT_EQ(-1.0f, bleedbox.bottom); + EXPECT_EQ(3.0f, bleedbox.right); + EXPECT_EQ(10.0f, bleedbox.top); - // NULL arg call is a no-op. - FPDFPage_InsertClipPath(nullptr, clip); + UnloadPage(page); +} - // Do actual work. - FPDFPage_InsertClipPath(page, clip); +TEST_F(FPDFTransformEmbedderTest, NoTrimBox) { + ASSERT_TRUE(OpenDocument("hello_world.pdf")); + ASSERT_EQ(1, FPDF_GetPageCount(document())); - // TODO(tsepez): test how inserting path affects page rendering. + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + FS_RECTF trimbox = {-11.0f, 0.0f, 3.0f, -10.0f}; + EXPECT_FALSE(FPDFPage_GetTrimBox(page, &trimbox.left, &trimbox.bottom, + &trimbox.right, &trimbox.top)); + EXPECT_EQ(-11.0f, trimbox.left); + EXPECT_EQ(-10.0f, trimbox.bottom); + EXPECT_EQ(3.0f, trimbox.right); + EXPECT_EQ(0.0f, trimbox.top); - FPDF_DestroyClipPath(clip); UnloadPage(page); } @@ -150,15 +177,34 @@ TEST_F(FPDFTransformEmbedderTest, NoArtBox) { FPDF_PAGE page = LoadPage(0); ASSERT_TRUE(page); - float left = -1.0f; - float bottom = -1.0f; - float right = 3.0f; - float top = 0.0f; - EXPECT_FALSE(FPDFPage_GetArtBox(page, &left, &bottom, &right, &top)); - EXPECT_EQ(-1.0f, left); - EXPECT_EQ(-1.0f, bottom); - EXPECT_EQ(3.0f, right); - EXPECT_EQ(0.0f, top); + FS_RECTF artbox = {-1.0f, 0.0f, 3.0f, -1.0f}; + EXPECT_FALSE(FPDFPage_GetArtBox(page, &artbox.left, &artbox.bottom, + &artbox.right, &artbox.top)); + EXPECT_EQ(-1.0f, artbox.left); + EXPECT_EQ(-1.0f, artbox.bottom); + EXPECT_EQ(3.0f, artbox.right); + EXPECT_EQ(0.0f, artbox.top); + + UnloadPage(page); +} + +TEST_F(FPDFTransformEmbedderTest, ClipPath) { + ASSERT_TRUE(OpenDocument("hello_world.pdf")); + + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + FPDF_CLIPPATH clip = FPDF_CreateClipPath(10.0f, 10.0f, 90.0f, 90.0f); + EXPECT_TRUE(clip); + // NULL arg call is a no-op. + FPDFPage_InsertClipPath(nullptr, clip); + + // Do actual work. + FPDFPage_InsertClipPath(page, clip); + + // TODO(tsepez): test how inserting path affects page rendering. + + FPDF_DestroyClipPath(clip); UnloadPage(page); } diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c index 3aa40cacf2..3ec51e7799 100644 --- a/fpdfsdk/fpdf_view_c_api_test.c +++ b/fpdfsdk/fpdf_view_c_api_test.c @@ -333,12 +333,16 @@ int CheckPDFiumCApi() { // fpdf_transformpage.h CHK(FPDFPageObj_TransformClipPath); CHK(FPDFPage_GetArtBox); + CHK(FPDFPage_GetBleedBox); CHK(FPDFPage_GetCropBox); CHK(FPDFPage_GetMediaBox); + CHK(FPDFPage_GetTrimBox); CHK(FPDFPage_InsertClipPath); CHK(FPDFPage_SetArtBox); + CHK(FPDFPage_SetBleedBox); CHK(FPDFPage_SetCropBox); CHK(FPDFPage_SetMediaBox); + CHK(FPDFPage_SetTrimBox); CHK(FPDFPage_TransFormWithClip); CHK(FPDF_CreateClipPath); CHK(FPDF_DestroyClipPath); diff --git a/public/fpdf_transformpage.h b/public/fpdf_transformpage.h index c1abe76979..899e5c6058 100644 --- a/public/fpdf_transformpage.h +++ b/public/fpdf_transformpage.h @@ -44,6 +44,36 @@ FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetCropBox(FPDF_PAGE page, float right, float top); +/** + * Set "BleedBox" entry to the page dictionary. + * + * page - Handle to a page. + * left - The left of the rectangle. + * bottom - The bottom of the rectangle. + * right - The right of the rectangle. + * top - The top of the rectangle. + */ +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetBleedBox(FPDF_PAGE page, + float left, + float bottom, + float right, + float top); + +/** + * Set "TrimBox" entry to the page dictionary. + * + * page - Handle to a page. + * left - The left of the rectangle. + * bottom - The bottom of the rectangle. + * right - The right of the rectangle. + * top - The top of the rectangle. + */ +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetTrimBox(FPDF_PAGE page, + float left, + float bottom, + float right, + float top); + /** * Set "ArtBox" entry to the page dictionary. * @@ -95,6 +125,42 @@ FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetCropBox(FPDF_PAGE page, float* right, float* top); +/** + * Get "BleedBox" entry from the page dictionary. + * + * page - Handle to a page. + * left - Pointer to a float value receiving the left of the rectangle. + * bottom - Pointer to a float value receiving the bottom of the rectangle. + * right - Pointer to a float value receiving the right of the rectangle. + * top - Pointer to a float value receiving the top of the rectangle. + * + * On success, return true and write to the out parameters. Otherwise return + * false and leave the out parameters unmodified. + */ +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetBleedBox(FPDF_PAGE page, + float* left, + float* bottom, + float* right, + float* top); + +/** + * Get "TrimBox" entry from the page dictionary. + * + * page - Handle to a page. + * left - Pointer to a float value receiving the left of the rectangle. + * bottom - Pointer to a float value receiving the bottom of the rectangle. + * right - Pointer to a float value receiving the right of the rectangle. + * top - Pointer to a float value receiving the top of the rectangle. + * + * On success, return true and write to the out parameters. Otherwise return + * false and leave the out parameters unmodified. + */ +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetTrimBox(FPDF_PAGE page, + float* left, + float* bottom, + float* right, + float* top); + /** * Get "ArtBox" entry from the page dictionary. * diff --git a/testing/resources/cropped_text.in b/testing/resources/cropped_text.in index d3812dc476..d6e2d602f9 100644 --- a/testing/resources/cropped_text.in +++ b/testing/resources/cropped_text.in @@ -41,6 +41,8 @@ endobj /Parent 2 0 R /MediaBox [ 0 0 200 200 ] /CropBox [ 50 50 150 150 ] + /BleedBox [ 50 60 140 145 ] + /TrimBox [ 55 60 140 145 ] /ArtBox [ 55 65 140 145 ] /Resources << /Font << @@ -56,6 +58,8 @@ endobj /Parent 2 0 R /MediaBox [ -50 -50 200 200 ] /CropBox [ 50 50 150 150 ] + /BleedBox [ 0 10 150 145 ] + /TrimBox [ 25 30 140 145 ] /ArtBox [ 50 60 135 140 ] /Resources << /Font << @@ -71,6 +75,8 @@ endobj /Parent 2 0 R /MediaBox [ 0 0 200 200 ] /CropBox [ 60 60 150 150 ] + /BleedBox [ 10 20 150 145 ] + /TrimBox [ 35 30 140 145 ] /ArtBox [ 65 75 140 148 ] /Resources << /Font << @@ -86,6 +92,8 @@ endobj /Parent 2 0 R /MediaBox [ 0 0 200 200 ] /CropBox [ 150 150 60 60 ] + /BleedBox [ 160 165 0 10 ] + /TrimBox [ 155 165 25 30 ] /ArtBox [ 140 145 65 70 ] /Resources << /Font << diff --git a/testing/resources/cropped_text.pdf b/testing/resources/cropped_text.pdf index 676d44b49a..3a93dbb158 100644 --- a/testing/resources/cropped_text.pdf +++ b/testing/resources/cropped_text.pdf @@ -42,6 +42,8 @@ endobj /Parent 2 0 R /MediaBox [ 0 0 200 200 ] /CropBox [ 50 50 150 150 ] + /BleedBox [ 50 60 140 145 ] + /TrimBox [ 55 60 140 145 ] /ArtBox [ 55 65 140 145 ] /Resources << /Font << @@ -57,6 +59,8 @@ endobj /Parent 2 0 R /MediaBox [ -50 -50 200 200 ] /CropBox [ 50 50 150 150 ] + /BleedBox [ 0 10 150 145 ] + /TrimBox [ 25 30 140 145 ] /ArtBox [ 50 60 135 140 ] /Resources << /Font << @@ -72,6 +76,8 @@ endobj /Parent 2 0 R /MediaBox [ 0 0 200 200 ] /CropBox [ 60 60 150 150 ] + /BleedBox [ 10 20 150 145 ] + /TrimBox [ 35 30 140 145 ] /ArtBox [ 65 75 140 148 ] /Resources << /Font << @@ -87,6 +93,8 @@ endobj /Parent 2 0 R /MediaBox [ 0 0 200 200 ] /CropBox [ 150 150 60 60 ] + /BleedBox [ 160 165 0 10 ] + /TrimBox [ 155 165 25 30 ] /ArtBox [ 140 145 65 70 ] /Resources << /Font << @@ -106,13 +114,13 @@ xref 0000000229 00000 n 0000000305 00000 n 0000000439 00000 n -0000000666 00000 n -0000000897 00000 n -0000001124 00000 n +0000000725 00000 n +0000001014 00000 n +0000001300 00000 n trailer << /Root 1 0 R /Size 10 >> startxref -1351 +1585 %%EOF -- cgit v1.2.3