| /* |
| * Copyright (C) 2019 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| * THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #import "config.h" |
| #import "TestPDFDocument.h" |
| |
| #if HAVE(PDFKIT) |
| |
| #import <WebCore/ColorMac.h> |
| #import <pal/spi/cg/CoreGraphicsSPI.h> |
| |
| namespace TestWebKitAPI { |
| |
| #if PLATFORM(MAC) |
| CGRect toCGRect(NSRect rect) { return NSRectToCGRect(rect); } |
| NSPoint toPlatformPoint(CGPoint point) { return NSPointFromCGPoint(point); } |
| #else |
| CGRect toCGRect(CGRect rect) { return rect; } |
| NSPoint toPlatformPoint(CGPoint point) { return point; } |
| #endif |
| |
| // Annotations |
| TestPDFAnnotation::TestPDFAnnotation(PDFAnnotation *annotation) |
| : m_annotation(annotation) |
| { |
| } |
| |
| bool TestPDFAnnotation::isLink() const |
| { |
| bool isLink = [m_annotation.get().type isEqualToString:@"Link"]; |
| if (isLink) |
| ASSERT([m_annotation.get().action isKindOfClass:[PDFActionURL class]]); |
| return isLink; |
| } |
| |
| CGRect TestPDFAnnotation::bounds() const |
| { |
| return toCGRect(m_annotation.get().bounds); |
| } |
| |
| NSURL *TestPDFAnnotation::linkURL() const |
| { |
| if (!isLink()) |
| return nil; |
| return ((PDFActionURL *)m_annotation.get().action).URL; |
| } |
| |
| // Pages |
| |
| Ref<TestPDFPage> TestPDFPage::create(PDFPage *page) |
| { |
| return adoptRef(*new TestPDFPage(page)); |
| } |
| |
| TestPDFPage::TestPDFPage(PDFPage *page) |
| : m_page(page) |
| { |
| } |
| |
| const Vector<TestPDFAnnotation>& TestPDFPage::annotations() |
| { |
| if (!m_annotations) { |
| m_annotations = Vector<TestPDFAnnotation>(); |
| for (PDFAnnotation *annotation in m_page.get().annotations) |
| m_annotations->append({ annotation }); |
| } |
| |
| return *m_annotations; |
| } |
| |
| size_t TestPDFPage::characterCount() const |
| { |
| return text().length(); |
| } |
| |
| inline bool shouldStrip(UChar character) |
| { |
| // This is a list of trailing and leading white space characters we've seen in PDF generation. |
| // It can be expanded if we see more popup. |
| return character == ' ' || character == '\n'; |
| } |
| |
| String TestPDFPage::text() const |
| { |
| if (!m_textWithoutSurroundingWhitespace) |
| m_textWithoutSurroundingWhitespace = String(m_page.get().string).stripLeadingAndTrailingCharacters(shouldStrip); |
| |
| return *m_textWithoutSurroundingWhitespace; |
| } |
| |
| CGRect TestPDFPage::rectForCharacterAtIndex(size_t index) const |
| { |
| return toCGRect([m_page characterBoundsAtIndex:index]); |
| } |
| |
| size_t TestPDFPage::characterIndexAtPoint(CGPoint point) const |
| { |
| return [m_page characterIndexAtPoint:toPlatformPoint(point)]; |
| } |
| |
| CGRect TestPDFPage::bounds() const |
| { |
| return toCGRect([m_page boundsForBox:kPDFDisplayBoxMediaBox]); |
| } |
| |
| |
| WebCore::Color TestPDFPage::colorAtPoint(int x, int y) const |
| { |
| auto boundsRect = bounds(); |
| auto colorSpace = adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceSRGB)); |
| auto context = adoptCF(CGBitmapContextCreate(NULL, boundsRect.size.width, boundsRect.size.height, 8, 0, colorSpace.get(), static_cast<uint32_t>(kCGImageAlphaPremultipliedLast) | static_cast<uint32_t>(kCGBitmapByteOrder32Big))); |
| |
| auto cgPage = m_page.get().pageRef; |
| CGContextDrawPDFPageWithAnnotations(context.get(), cgPage, nullptr); |
| |
| const unsigned char* pixel = (const unsigned char*)CGBitmapContextGetData(context.get()); |
| size_t i = (y * x * 4) + (x * 4); |
| |
| auto r = pixel[i]; |
| auto g = pixel[i + 1]; |
| auto b = pixel[i + 2]; |
| auto a = pixel[i + 3]; |
| |
| if (!a) |
| return WebCore::Color::transparentBlack; |
| return WebCore::makeFromComponentsClampingExceptAlpha<WebCore::SRGBA<uint8_t>>(r * 255 / a, g * 255 / a, b * 255 / a, a); |
| } |
| |
| // Documents |
| |
| Ref<TestPDFDocument> TestPDFDocument::createFromData(NSData *data) |
| { |
| return adoptRef(*new TestPDFDocument(data)); |
| } |
| |
| TestPDFDocument::TestPDFDocument(NSData *data) |
| : m_document(adoptNS([[PDFDocument alloc] initWithData:data])) |
| , m_pages(pageCount()) |
| { |
| } |
| |
| size_t TestPDFDocument::pageCount() const |
| { |
| return [m_document pageCount]; |
| } |
| |
| TestPDFPage* TestPDFDocument::page(size_t index) |
| { |
| if (index >= pageCount()) |
| return nullptr; |
| if (!m_pages[index]) |
| m_pages[index] = TestPDFPage::create([m_document pageAtIndex:index]); |
| return m_pages[index].get(); |
| } |
| |
| } // namespace TestWebKitAPI |
| |
| #endif // HAVE(PDFKIT) |