PDF a11y: new API for fill and stroke colors The text fill and stroke colors are now exposed by FPDFText_GetFillColor() and FPDFText_GetStrokeColor(). Each API takes separated parameters for R, G, B and A values. Bug: chromium:985604 Change-Id: Ibb9990eba303b818674f0e61b30f74e779a9f156 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/60110 Reviewed-by: Lei Zhang <thestig@chromium.org> Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxge/fx_dib.h b/core/fxge/fx_dib.h index f61d1f2..c292e99 100644 --- a/core/fxge/fx_dib.h +++ b/core/fxge/fx_dib.h
@@ -96,6 +96,10 @@ return (bgr >> 16) & 0xff; } +constexpr unsigned int FXSYS_GetUnsignedAlpha(float alpha) { + return static_cast<unsigned int>(alpha * 255.f + 0.5f); +} + #define FXSYS_GetCValue(cmyk) ((uint8_t)((cmyk) >> 24) & 0xff) #define FXSYS_GetMValue(cmyk) ((uint8_t)((cmyk) >> 16) & 0xff) #define FXSYS_GetYValue(cmyk) ((uint8_t)((cmyk) >> 8) & 0xff)
diff --git a/fpdfsdk/fpdf_editpage.cpp b/fpdfsdk/fpdf_editpage.cpp index 802cd90..0917b64 100644 --- a/fpdfsdk/fpdf_editpage.cpp +++ b/fpdfsdk/fpdf_editpage.cpp
@@ -136,10 +136,6 @@ return pMarkItem && pPageObj->m_ContentMarks.ContainsItem(pMarkItem); } -unsigned int GetUnsignedAlpha(float alpha) { - return static_cast<unsigned int>(alpha * 255.f + 0.5f); -} - CPDF_FormObject* CPDFFormObjectFromFPDFPageObject(FPDF_PAGEOBJECT page_object) { auto* pPageObj = CPDFPageObjectFromFPDFPageObject(page_object); return pPageObj ? pPageObj->AsForm() : nullptr; @@ -711,7 +707,7 @@ *R = FXSYS_GetRValue(fillColor); *G = FXSYS_GetGValue(fillColor); *B = FXSYS_GetBValue(fillColor); - *A = GetUnsignedAlpha(pPageObj->m_GeneralState.GetFillAlpha()); + *A = FXSYS_GetUnsignedAlpha(pPageObj->m_GeneralState.GetFillAlpha()); return true; } @@ -765,7 +761,7 @@ *R = FXSYS_GetRValue(strokeColor); *G = FXSYS_GetGValue(strokeColor); *B = FXSYS_GetBValue(strokeColor); - *A = GetUnsignedAlpha(pPageObj->m_GeneralState.GetStrokeAlpha()); + *A = FXSYS_GetUnsignedAlpha(pPageObj->m_GeneralState.GetStrokeAlpha()); return true; }
diff --git a/fpdfsdk/fpdf_text.cpp b/fpdfsdk/fpdf_text.cpp index 4d29d61..e204465 100644 --- a/fpdfsdk/fpdf_text.cpp +++ b/fpdfsdk/fpdf_text.cpp
@@ -144,6 +144,57 @@ charinfo.m_pTextObj->GetTextRenderMode()); } +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFText_GetFillColor(FPDF_TEXTPAGE text_page, + int index, + unsigned int* R, + unsigned int* G, + unsigned int* B, + unsigned int* A) { + CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index); + if (!textpage || !R || !G || !B || !A) + return false; + + FPDF_CHAR_INFO charinfo; + textpage->GetCharInfo(index, &charinfo); + if (!charinfo.m_pTextObj) + return false; + + FX_COLORREF fill_color = charinfo.m_pTextObj->m_ColorState.GetFillColorRef(); + *R = FXSYS_GetRValue(fill_color); + *G = FXSYS_GetGValue(fill_color); + *B = FXSYS_GetBValue(fill_color); + *A = FXSYS_GetUnsignedAlpha( + charinfo.m_pTextObj->m_GeneralState.GetFillAlpha()); + return true; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFText_GetStrokeColor(FPDF_TEXTPAGE text_page, + int index, + unsigned int* R, + unsigned int* G, + unsigned int* B, + unsigned int* A) { + CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index); + if (!textpage || !R || !G || !B || !A) + return false; + + FPDF_CHAR_INFO charinfo; + textpage->GetCharInfo(index, &charinfo); + if (!charinfo.m_pTextObj) + return false; + + FX_COLORREF stroke_color = + charinfo.m_pTextObj->m_ColorState.GetStrokeColorRef(); + *R = FXSYS_GetRValue(stroke_color); + *G = FXSYS_GetGValue(stroke_color); + *B = FXSYS_GetBValue(stroke_color); + *A = FXSYS_GetUnsignedAlpha( + charinfo.m_pTextObj->m_GeneralState.GetStrokeAlpha()); + return true; +} + FPDF_EXPORT double FPDF_CALLCONV FPDFText_GetCharAngle(FPDF_TEXTPAGE text_page, int index) { CPDF_TextPage* textpage = GetTextPageForValidIndex(text_page, index);
diff --git a/fpdfsdk/fpdf_text_embeddertest.cpp b/fpdfsdk/fpdf_text_embeddertest.cpp index 40d0c97..e4d11ed 100644 --- a/fpdfsdk/fpdf_text_embeddertest.cpp +++ b/fpdfsdk/fpdf_text_embeddertest.cpp
@@ -1297,3 +1297,69 @@ FPDFText_ClosePage(text_page); UnloadPage(page); } + +TEST_F(FPDFTextEmbedderTest, GetFillColor) { + ASSERT_TRUE(OpenDocument("text_color.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page); + ASSERT_TRUE(text_page); + + ASSERT_EQ(1, FPDFText_CountChars(text_page)); + + ASSERT_FALSE( + FPDFText_GetFillColor(nullptr, 0, nullptr, nullptr, nullptr, nullptr)); + ASSERT_FALSE( + FPDFText_GetFillColor(text_page, -1, nullptr, nullptr, nullptr, nullptr)); + ASSERT_FALSE(FPDFText_GetFillColor(text_page, 314, nullptr, nullptr, nullptr, + nullptr)); + ASSERT_FALSE( + FPDFText_GetFillColor(text_page, 0, nullptr, nullptr, nullptr, nullptr)); + + unsigned int r; + unsigned int g; + unsigned int b; + unsigned int a; + ASSERT_TRUE(FPDFText_GetFillColor(text_page, 0, &r, &g, &b, &a)); + ASSERT_EQ(0xffu, r); + ASSERT_EQ(0u, g); + ASSERT_EQ(0u, b); + ASSERT_EQ(0xffu, a); + + FPDFText_ClosePage(text_page); + UnloadPage(page); +} + +TEST_F(FPDFTextEmbedderTest, GetStrokeColor) { + ASSERT_TRUE(OpenDocument("text_color.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page); + ASSERT_TRUE(text_page); + + ASSERT_EQ(1, FPDFText_CountChars(text_page)); + + ASSERT_FALSE( + FPDFText_GetStrokeColor(nullptr, 0, nullptr, nullptr, nullptr, nullptr)); + ASSERT_FALSE(FPDFText_GetStrokeColor(text_page, -1, nullptr, nullptr, nullptr, + nullptr)); + ASSERT_FALSE(FPDFText_GetStrokeColor(text_page, 314, nullptr, nullptr, + nullptr, nullptr)); + ASSERT_FALSE(FPDFText_GetStrokeColor(text_page, 0, nullptr, nullptr, nullptr, + nullptr)); + + unsigned int r; + unsigned int g; + unsigned int b; + unsigned int a; + ASSERT_TRUE(FPDFText_GetStrokeColor(text_page, 0, &r, &g, &b, &a)); + ASSERT_EQ(0u, r); + ASSERT_EQ(0xffu, g); + ASSERT_EQ(0u, b); + ASSERT_EQ(0xffu, a); + + FPDFText_ClosePage(text_page); + UnloadPage(page); +}
diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c index 1e00348..0a7baf7 100644 --- a/fpdfsdk/fpdf_view_c_api_test.c +++ b/fpdfsdk/fpdf_view_c_api_test.c
@@ -336,12 +336,14 @@ CHK(FPDFText_GetCharBox); CHK(FPDFText_GetCharIndexAtPos); CHK(FPDFText_GetCharOrigin); + CHK(FPDFText_GetFillColor); CHK(FPDFText_GetFontInfo); CHK(FPDFText_GetFontSize); CHK(FPDFText_GetFontWeight); CHK(FPDFText_GetRect); CHK(FPDFText_GetSchCount); CHK(FPDFText_GetSchResultIndex); + CHK(FPDFText_GetStrokeColor); CHK(FPDFText_GetText); CHK(FPDFText_GetTextRenderMode); CHK(FPDFText_GetUnicode);
diff --git a/public/fpdf_text.h b/public/fpdf_text.h index c7e9d71..04664be 100644 --- a/public/fpdf_text.h +++ b/public/fpdf_text.h
@@ -142,6 +142,60 @@ FPDFText_GetTextRenderMode(FPDF_TEXTPAGE text_page, int index); // Experimental API. +// Function: FPDFText_GetFillColor +// Get the fill color of a particular character. +// Parameters: +// text_page - Handle to a text page information structure. +// Returned by FPDFText_LoadPage function. +// index - Zero-based index of the character. +// R - Pointer to an unsigned int number receiving the +// red value of the fill color. +// G - Pointer to an unsigned int number receiving the +// green value of the fill color. +// B - Pointer to an unsigned int number receiving the +// blue value of the fill color. +// A - Pointer to an unsigned int number receiving the +// alpha value of the fill color. +// Return value: +// Whether the call succeeded. If false, |R|, |G|, |B| and |A| are +// unchanged. +// +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFText_GetFillColor(FPDF_TEXTPAGE text_page, + int index, + unsigned int* R, + unsigned int* G, + unsigned int* B, + unsigned int* A); + +// Experimental API. +// Function: FPDFText_GetStrokeColor +// Get the stroke color of a particular character. +// Parameters: +// text_page - Handle to a text page information structure. +// Returned by FPDFText_LoadPage function. +// index - Zero-based index of the character. +// R - Pointer to an unsigned int number receiving the +// red value of the stroke color. +// G - Pointer to an unsigned int number receiving the +// green value of the stroke color. +// B - Pointer to an unsigned int number receiving the +// blue value of the stroke color. +// A - Pointer to an unsigned int number receiving the +// alpha value of the stroke color. +// Return value: +// Whether the call succeeded. If false, |R|, |G|, |B| and |A| are +// unchanged. +// +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFText_GetStrokeColor(FPDF_TEXTPAGE text_page, + int index, + unsigned int* R, + unsigned int* G, + unsigned int* B, + unsigned int* A); + +// Experimental API. // Function: FPDFText_GetCharAngle // Get character rotation angle. // Parameters:
diff --git a/testing/resources/text_color.in b/testing/resources/text_color.in new file mode 100644 index 0000000..7e76a39 --- /dev/null +++ b/testing/resources/text_color.in
@@ -0,0 +1,48 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R +>> +endobj +{{object 2 0}} << + /Type /Pages + /MediaBox [ 0 0 200 200 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Resources << + /Font << + /F1 4 0 R + >> + >> + /Contents 5 0 R +>> +endobj +{{object 4 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Times-Roman +>> +endobj +{{object 5 0}} << + {{streamlen}} +>> +stream +BT +10 160 Td +/F1 36 Tf +0 1 0 RG +1 0 0 rg +2 Tr +(0) Tj +ET +endstream +endobj +{{xref}} +{{trailer}} +{{startxref}} +%%EOF
diff --git a/testing/resources/text_color.pdf b/testing/resources/text_color.pdf new file mode 100644 index 0000000..8dbcdd1 --- /dev/null +++ b/testing/resources/text_color.pdf
@@ -0,0 +1,60 @@ +%PDF-1.7 +% ò¤ô +1 0 obj << + /Type /Catalog + /Pages 2 0 R +>> +endobj +2 0 obj << + /Type /Pages + /MediaBox [ 0 0 200 200 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +3 0 obj << + /Type /Page + /Parent 2 0 R + /Resources << + /Font << + /F1 4 0 R + >> + >> + /Contents 5 0 R +>> +endobj +4 0 obj << + /Type /Font + /Subtype /Type1 + /BaseFont /Times-Roman +>> +endobj +5 0 obj << + /Length 56 +>> +stream +BT +10 160 Td +/F1 36 Tf +0 1 0 RG +1 0 0 rg +2 Tr +(0) Tj +ET +endstream +endobj +xref +0 6 +0000000000 65535 f +0000000015 00000 n +0000000068 00000 n +0000000161 00000 n +0000000287 00000 n +0000000365 00000 n +trailer << + /Root 1 0 R + /Size 6 +>> +startxref +472 +%%EOF