2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								/*
							 | 
						
					
						
							
								
									
										
										
										
											2022-03-05 00:36:05 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								 * Copyright (c) 2021-2022, Matthew Olsson <mattco@serenityos.org>
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 *
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 * SPDX-License-Identifier: BSD-2-Clause
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 */
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#pragma once
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <AK/Format.h>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <LibGfx/AffineTransform.h>
							 | 
						
					
						
							
								
									
										
										
										
											2022-03-24 11:50:37 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								#include <LibGfx/AntiAliasingPainter.h>
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <LibGfx/Bitmap.h>
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-09 09:28:38 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								#include <LibGfx/Font/Font.h>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <LibGfx/Font/FontDatabase.h>
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <LibGfx/Painter.h>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <LibGfx/Path.h>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <LibGfx/Point.h>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <LibGfx/Rect.h>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <LibGfx/Size.h>
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-27 14:01:37 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								#include <LibPDF/ColorSpace.h>
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <LibPDF/Document.h>
							 | 
						
					
						
							
								
									
										
										
										
											2022-03-24 22:14:50 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								#include <LibPDF/Fonts/PDFFont.h>
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <LibPDF/Object.h>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								namespace PDF {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								enum class LineCapStyle : u8 {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ButtCap = 0,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    RoundCap = 1,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    SquareCap = 2,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								enum class LineJoinStyle : u8 {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Miter = 0,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Round = 1,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Bevel = 2,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								struct LineDashPattern {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Vector<int> pattern;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    int phase;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								enum class TextRenderingMode : u8 {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Fill = 0,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Stroke = 1,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    FillThenStroke = 2,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Invisible = 3,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    FillAndClip = 4,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    StrokeAndClip = 5,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    FillStrokeAndClip = 6,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Clip = 7,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								struct TextState {
							 | 
						
					
						
							
								
									
										
										
										
											2022-03-05 00:36:05 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    float character_spacing { 0.0f };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    float word_spacing { 0.0f };
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    float horizontal_scaling { 1.0f };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    float leading { 0.0f };
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-28 11:55:51 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    float font_size { 12.0f };
							 | 
						
					
						
							
								
									
										
										
										
											2022-03-08 12:10:06 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    RefPtr<PDFFont> font;
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    TextRenderingMode rendering_mode { TextRenderingMode::Fill };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    float rise { 0.0f };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    bool knockout { true };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-11-23 21:03:26 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								struct ClippingPaths {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Gfx::Path current;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Gfx::Path next;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								struct GraphicsState {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Gfx::AffineTransform ctm;
							 | 
						
					
						
							
								
									
										
										
										
											2022-11-23 21:03:26 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ClippingPaths clipping_paths;
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-27 14:01:37 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    RefPtr<ColorSpace> stroke_color_space { DeviceGrayColorSpace::the() };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    RefPtr<ColorSpace> paint_color_space { DeviceGrayColorSpace::the() };
							 | 
						
					
						
							
								
									
										
										
										
											2023-12-05 12:51:42 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ColorOrStyle stroke_style { Color::Black };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ColorOrStyle paint_style { Color::Black };
							 | 
						
					
						
							
								
									
										
										
										
											2023-12-16 17:49:34 +03:30
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ByteString color_rendering_intent { "RelativeColorimetric"sv };
							 | 
						
					
						
							
								
									
										
										
										
											2023-07-12 14:25:22 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    float flatness_tolerance { 0.0f };
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    float line_width { 1.0f };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    LineCapStyle line_cap_style { LineCapStyle::ButtCap };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    LineJoinStyle line_join_style { LineJoinStyle::Miter };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    float miter_limit { 10.0f };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    LineDashPattern line_dash_pattern { {}, 0 };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    TextState text_state {};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-11-23 21:11:29 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								struct RenderingPreferences {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    bool show_clipping_paths { false };
							 | 
						
					
						
							
								
									
										
											 
										 
										
											
												LibPDF: Add initial image display support
After adding support for XObject Form rendering, the next was to display
XObject images. This commit adds this initial support,
Images come in many shapes and forms: encodings: color spaces, bits per
component, width, height, etc. This initial support is constrained to
the color spaces we currently support, to images that use 8 bits per
component, to images that do *not* use the JPXDecode filter, and that
are not Masks. There are surely other constraints that aren't considered
in this initial support, so expect breakage here and there.
In addition to supporting images, we also support applying an alpha mask
(SMask) on them. Additionally, a new rendering preference allows to skip
image loading and rendering altogether, instead showing an empty
rectangle as a placeholder (useful for when actual images are not
supported). Since RenderingPreferences is becoming a bit more complex,
we add a hash option that will allow us to keep track of different
preferences (e.g., in a HashMap).
											
										 
										
											2022-11-25 02:01:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    bool show_images { true };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-16 20:45:12 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    bool clip_images { true };
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-19 20:00:32 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    bool clip_paths { true };
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-19 20:01:23 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    bool clip_text { true };
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-16 20:45:12 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
											 
										 
										
											
												LibPDF: Add initial image display support
After adding support for XObject Form rendering, the next was to display
XObject images. This commit adds this initial support,
Images come in many shapes and forms: encodings: color spaces, bits per
component, width, height, etc. This initial support is constrained to
the color spaces we currently support, to images that use 8 bits per
component, to images that do *not* use the JPXDecode filter, and that
are not Masks. There are surely other constraints that aren't considered
in this initial support, so expect breakage here and there.
In addition to supporting images, we also support applying an alpha mask
(SMask) on them. Additionally, a new rendering preference allows to skip
image loading and rendering altogether, instead showing an empty
rectangle as a placeholder (useful for when actual images are not
supported). Since RenderingPreferences is becoming a bit more complex,
we add a hash option that will allow us to keep track of different
preferences (e.g., in a HashMap).
											
										 
										
											2022-11-25 02:01:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    unsigned hash() const
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return static_cast<unsigned>(show_clipping_paths) | static_cast<unsigned>(show_images) << 1;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    }
							 | 
						
					
						
							
								
									
										
										
										
											2022-11-23 21:11:29 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class Renderer {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								public:
							 | 
						
					
						
							
								
									
										
										
										
											2023-12-07 12:53:13 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    static PDFErrorsOr<void> render(Document&, Page const&, RefPtr<Gfx::Bitmap>, Color background_color, RenderingPreferences preferences);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
											
												LibPDF: Cache fonts per page
Previously, every time a page switched fonts, we'd completely
re-parse the font.
Now, we cache fonts in Renderer, effectively caching them per page.
It'd be nice to have an LRU cache across pages too, but that's a
bigger change, and this already helps a lot.
Font size is part of the cache key, which means we re-parse the same
font at different font sizes. That could be better too, but again,
it's a big help as-is already.
Takes rendering the 1310 pages of the PDF 1.7 reference with
    Build/lagom/bin/pdf --debugging-stats \
        ~/Downloads/pdf_reference_1-7.pdf
from 71 s to 11s :^)
Going through pages especially in the index is noticeably snappier.
(On the PDF 2.0 spec, ISO_32000-2-2020_sponsored.pdf, it's less
dramatic: From 19s to 16s.)
											
										 
										
											2023-10-10 13:55:35 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    struct FontCacheKey {
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-16 20:15:58 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        NonnullRefPtr<DictObject> font_dictionary;
							 | 
						
					
						
							
								
									
										
										
											
												LibPDF: Cache fonts per page
Previously, every time a page switched fonts, we'd completely
re-parse the font.
Now, we cache fonts in Renderer, effectively caching them per page.
It'd be nice to have an LRU cache across pages too, but that's a
bigger change, and this already helps a lot.
Font size is part of the cache key, which means we re-parse the same
font at different font sizes. That could be better too, but again,
it's a big help as-is already.
Takes rendering the 1310 pages of the PDF 1.7 reference with
    Build/lagom/bin/pdf --debugging-stats \
        ~/Downloads/pdf_reference_1-7.pdf
from 71 s to 11s :^)
Going through pages especially in the index is noticeably snappier.
(On the PDF 2.0 spec, ISO_32000-2-2020_sponsored.pdf, it's less
dramatic: From 19s to 16s.)
											
										 
										
											2023-10-10 13:55:35 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        float font_size;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        bool operator==(FontCacheKey const&) const = default;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-14 10:11:39 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ALWAYS_INLINE GraphicsState const& state() const { return m_graphics_state_stack.last(); }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ALWAYS_INLINE TextState const& text_state() const { return state().text_state; }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Gfx::AffineTransform const& calculate_text_rendering_matrix() const;
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-15 07:51:56 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    PDFErrorOr<void> render_type3_glyph(Gfx::FloatPoint, StreamObject const&, Gfx::AffineTransform const&, Optional<NonnullRefPtr<DictObject>>);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								private:
							 | 
						
					
						
							
								
									
										
										
										
											2023-12-07 12:53:13 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Renderer(RefPtr<Document>, Page const&, RefPtr<Gfx::Bitmap>, Color background_color, RenderingPreferences);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
											
												LibPDF: Switch to best-effort PDF rendering
The current rendering routine aborts as soon as an error is found during
rendering, which potentially severely limits the contents we show on
screen. Moreover, whenever an error happens the PDFViewer widget shows
an error dialog, and doesn't display the bitmap that has been painted so
far.
This commit improves the situation in both fronts, implementing
rendering now with a best-effort approach. Firstly, execution of
operations isn't halted after an operand results in an error, but
instead execution of all operations is always attempted, and all
collected errors are returned in bulk. Secondly, PDFViewer now always
displays the resulting bitmap, regardless of error being produced or
not. To communicate errors, an on_render_errors callback has been added
so clients can subscribe to these events and handle them as appropriate.
											
										 
										
											2022-12-14 23:00:40 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    PDFErrorsOr<void> render();
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-11-21 13:28:41 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    PDFErrorOr<void> handle_operator(Operator const&, Optional<NonnullRefPtr<DictObject>> = {});
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#define V(name, snake_name, symbol) \
							 | 
						
					
						
							
								
									
										
										
										
											2023-10-20 11:55:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    PDFErrorOr<void> handle_##snake_name(ReadonlySpan<Value> args, Optional<NonnullRefPtr<DictObject>> = {});
							 | 
						
					
						
							
								
									
										
										
										
											2022-03-25 15:00:11 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ENUMERATE_OPERATORS(V)
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#undef V
							 | 
						
					
						
							
								
									
										
										
										
											2023-10-20 11:55:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    PDFErrorOr<void> handle_text_next_line_show_string(ReadonlySpan<Value> args, Optional<NonnullRefPtr<DictObject>> = {});
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    PDFErrorOr<void> handle_text_next_line_show_string_set_spacing(ReadonlySpan<Value> args, Optional<NonnullRefPtr<DictObject>> = {});
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-19 19:45:20 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    class ClipRAII {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    public:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ClipRAII(Renderer& renderer)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            : m_renderer(renderer)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            m_renderer.activate_clip();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ~ClipRAII() { m_renderer.deactivate_clip(); }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    private:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Renderer& m_renderer;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    };
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-16 20:38:13 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    void activate_clip();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void deactivate_clip();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-11-23 21:03:26 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    void begin_path_paint();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void end_path_paint();
							 | 
						
					
						
							
								
									
										
										
										
											2022-03-05 18:12:58 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    PDFErrorOr<void> set_graphics_state_from_dict(NonnullRefPtr<DictObject>);
							 | 
						
					
						
							
								
									
										
										
										
											2023-12-16 17:49:34 +03:30
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    PDFErrorOr<void> show_text(ByteString const&);
							 | 
						
					
						
							
								
									
										
										
										
											2023-12-22 18:56:42 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    struct LoadedImage {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        NonnullRefPtr<Gfx::Bitmap> bitmap;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        bool is_image_mask = false;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    PDFErrorOr<LoadedImage> load_image(NonnullRefPtr<StreamObject>);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
											 
										 
										
											
												LibPDF: Add initial image display support
After adding support for XObject Form rendering, the next was to display
XObject images. This commit adds this initial support,
Images come in many shapes and forms: encodings: color spaces, bits per
component, width, height, etc. This initial support is constrained to
the color spaces we currently support, to images that use 8 bits per
component, to images that do *not* use the JPXDecode filter, and that
are not Masks. There are surely other constraints that aren't considered
in this initial support, so expect breakage here and there.
In addition to supporting images, we also support applying an alpha mask
(SMask) on them. Additionally, a new rendering preference allows to skip
image loading and rendering altogether, instead showing an empty
rectangle as a placeholder (useful for when actual images are not
supported). Since RenderingPreferences is becoming a bit more complex,
we add a hash option that will allow us to keep track of different
preferences (e.g., in a HashMap).
											
										 
										
											2022-11-25 02:01:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    PDFErrorOr<void> show_image(NonnullRefPtr<StreamObject>);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    void show_empty_image(int width, int height);
							 | 
						
					
						
							
								
									
										
											 
										 
										
											
												LibPDF: Refactor parsing of ColorSpaces
ColorSpaces can be specified in two ways: with a stream as operands of
the color space operations (CS/cs), or as a separate PDF object, which
is then referred to by other means (e.g., from Image XObjects and other
entities). These two modes of addressing a ColorSpace are slightly
different and need to be addressed separately. However, the current
implementation embedded the full logic of the first case in the routine
that created ColorSpace objects.
This commit refactors the creation of ColorSpace to support both cases.
First, a new ColorSpaceFamily class encapsulates the static aspects of a
family, like its name or whether color space construction never requires
parameters. Then we define the supported ColorSpaceFamily objects.
On top of this also sit a breakage on how ColorSpaces are created. Two
methods are now offered: one only providing construction of no-argument
color spaces (and thus taking a simple name), and another taking an
ArrayObject, hence used to create ColorSpaces requiring arguments.
Finally, on top of *that* two ways to get a color space in the Renderer
are made available: the first creates a ColorSpace with a name and a
Resources dictionary, and another takes an Object. These model the two
addressing modes described above.
											
										 
										
											2022-11-24 12:40:24 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    PDFErrorOr<NonnullRefPtr<ColorSpace>> get_color_space_from_resources(Value const&, NonnullRefPtr<DictObject>);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    PDFErrorOr<NonnullRefPtr<ColorSpace>> get_color_space_from_document(NonnullRefPtr<Object>);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ALWAYS_INLINE GraphicsState& state() { return m_graphics_state_stack.last(); }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ALWAYS_INLINE TextState& text_state() { return state().text_state; }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    template<typename T>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ALWAYS_INLINE Gfx::Point<T> map(T x, T y) const;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    template<typename T>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ALWAYS_INLINE Gfx::Size<T> map(Gfx::Size<T>) const;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-23 12:53:38 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    template<typename T>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ALWAYS_INLINE Gfx::Rect<T> map(Gfx::Rect<T>) const;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-16 20:32:26 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Gfx::Path map(Gfx::Path const&) const;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2024-02-20 21:38:45 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    float line_width() const;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
											 
										 
										
											
												LibPDF: Add initial image display support
After adding support for XObject Form rendering, the next was to display
XObject images. This commit adds this initial support,
Images come in many shapes and forms: encodings: color spaces, bits per
component, width, height, etc. This initial support is constrained to
the color spaces we currently support, to images that use 8 bits per
component, to images that do *not* use the JPXDecode filter, and that
are not Masks. There are surely other constraints that aren't considered
in this initial support, so expect breakage here and there.
In addition to supporting images, we also support applying an alpha mask
(SMask) on them. Additionally, a new rendering preference allows to skip
image loading and rendering altogether, instead showing an empty
rectangle as a placeholder (useful for when actual images are not
supported). Since RenderingPreferences is becoming a bit more complex,
we add a hash option that will allow us to keep track of different
preferences (e.g., in a HashMap).
											
										 
										
											2022-11-25 02:01:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Gfx::AffineTransform calculate_image_space_transformation(int width, int height);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-16 20:15:58 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    PDFErrorOr<NonnullRefPtr<PDFFont>> get_font(FontCacheKey const&);
							 | 
						
					
						
							
								
									
										
										
											
												LibPDF: Cache fonts per page
Previously, every time a page switched fonts, we'd completely
re-parse the font.
Now, we cache fonts in Renderer, effectively caching them per page.
It'd be nice to have an LRU cache across pages too, but that's a
bigger change, and this already helps a lot.
Font size is part of the cache key, which means we re-parse the same
font at different font sizes. That could be better too, but again,
it's a big help as-is already.
Takes rendering the 1310 pages of the PDF 1.7 reference with
    Build/lagom/bin/pdf --debugging-stats \
        ~/Downloads/pdf_reference_1-7.pdf
from 71 s to 11s :^)
Going through pages especially in the index is noticeably snappier.
(On the PDF 2.0 spec, ISO_32000-2-2020_sponsored.pdf, it's less
dramatic: From 19s to 16s.)
											
										 
										
											2023-10-10 13:55:35 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-14 10:35:40 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    class ScopedState;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    RefPtr<Document> m_document;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    RefPtr<Gfx::Bitmap> m_bitmap;
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-01 11:16:11 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Page const& m_page;
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Gfx::Painter m_painter;
							 | 
						
					
						
							
								
									
										
										
										
											2022-03-24 11:50:37 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Gfx::AntiAliasingPainter m_anti_aliasing_painter;
							 | 
						
					
						
							
								
									
										
										
										
											2022-11-23 21:11:29 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    RenderingPreferences m_rendering_preferences;
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-23 11:43:28 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Gfx::Path m_current_path;
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Vector<GraphicsState> m_graphics_state_stack;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Gfx::AffineTransform m_text_matrix;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Gfx::AffineTransform m_text_line_matrix;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-14 10:11:39 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    bool mutable m_text_rendering_matrix_is_dirty { true };
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Gfx::AffineTransform mutable m_text_rendering_matrix;
							 | 
						
					
						
							
								
									
										
										
											
												LibPDF: Cache fonts per page
Previously, every time a page switched fonts, we'd completely
re-parse the font.
Now, we cache fonts in Renderer, effectively caching them per page.
It'd be nice to have an LRU cache across pages too, but that's a
bigger change, and this already helps a lot.
Font size is part of the cache key, which means we re-parse the same
font at different font sizes. That could be better too, but again,
it's a big help as-is already.
Takes rendering the 1310 pages of the PDF 1.7 reference with
    Build/lagom/bin/pdf --debugging-stats \
        ~/Downloads/pdf_reference_1-7.pdf
from 71 s to 11s :^)
Going through pages especially in the index is noticeably snappier.
(On the PDF 2.0 spec, ISO_32000-2-2020_sponsored.pdf, it's less
dramatic: From 19s to 16s.)
											
										 
										
											2023-10-10 13:55:35 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    HashMap<FontCacheKey, NonnullRefPtr<PDFFont>> m_font_cache;
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								namespace AK {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
											
												LibPDF: Cache fonts per page
Previously, every time a page switched fonts, we'd completely
re-parse the font.
Now, we cache fonts in Renderer, effectively caching them per page.
It'd be nice to have an LRU cache across pages too, but that's a
bigger change, and this already helps a lot.
Font size is part of the cache key, which means we re-parse the same
font at different font sizes. That could be better too, but again,
it's a big help as-is already.
Takes rendering the 1310 pages of the PDF 1.7 reference with
    Build/lagom/bin/pdf --debugging-stats \
        ~/Downloads/pdf_reference_1-7.pdf
from 71 s to 11s :^)
Going through pages especially in the index is noticeably snappier.
(On the PDF 2.0 spec, ISO_32000-2-2020_sponsored.pdf, it's less
dramatic: From 19s to 16s.)
											
										 
										
											2023-10-10 13:55:35 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								template<>
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-08 20:29:12 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								struct Traits<PDF::Renderer::FontCacheKey> : public DefaultTraits<PDF::Renderer::FontCacheKey> {
							 | 
						
					
						
							
								
									
										
										
											
												LibPDF: Cache fonts per page
Previously, every time a page switched fonts, we'd completely
re-parse the font.
Now, we cache fonts in Renderer, effectively caching them per page.
It'd be nice to have an LRU cache across pages too, but that's a
bigger change, and this already helps a lot.
Font size is part of the cache key, which means we re-parse the same
font at different font sizes. That could be better too, but again,
it's a big help as-is already.
Takes rendering the 1310 pages of the PDF 1.7 reference with
    Build/lagom/bin/pdf --debugging-stats \
        ~/Downloads/pdf_reference_1-7.pdf
from 71 s to 11s :^)
Going through pages especially in the index is noticeably snappier.
(On the PDF 2.0 spec, ISO_32000-2-2020_sponsored.pdf, it's less
dramatic: From 19s to 16s.)
											
										 
										
											2023-10-10 13:55:35 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    static unsigned hash(PDF::Renderer::FontCacheKey const& key)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-16 20:15:58 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return pair_int_hash(ptr_hash(key.font_dictionary.ptr()), int_hash(bit_cast<u32>(key.font_size)));
							 | 
						
					
						
							
								
									
										
										
											
												LibPDF: Cache fonts per page
Previously, every time a page switched fonts, we'd completely
re-parse the font.
Now, we cache fonts in Renderer, effectively caching them per page.
It'd be nice to have an LRU cache across pages too, but that's a
bigger change, and this already helps a lot.
Font size is part of the cache key, which means we re-parse the same
font at different font sizes. That could be better too, but again,
it's a big help as-is already.
Takes rendering the 1310 pages of the PDF 1.7 reference with
    Build/lagom/bin/pdf --debugging-stats \
        ~/Downloads/pdf_reference_1-7.pdf
from 71 s to 11s :^)
Going through pages especially in the index is noticeably snappier.
(On the PDF 2.0 spec, ISO_32000-2-2020_sponsored.pdf, it's less
dramatic: From 19s to 16s.)
											
										 
										
											2023-10-10 13:55:35 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								template<>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								struct Formatter<PDF::LineCapStyle> : Formatter<StringView> {
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-16 01:15:21 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ErrorOr<void> format(FormatBuilder& builder, PDF::LineCapStyle const& style)
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        switch (style) {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        case PDF::LineCapStyle::ButtCap:
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 20:23:24 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return builder.put_string("LineCapStyle::ButtCap"sv);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        case PDF::LineCapStyle::RoundCap:
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 20:23:24 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return builder.put_string("LineCapStyle::RoundCap"sv);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        case PDF::LineCapStyle::SquareCap:
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 20:23:24 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return builder.put_string("LineCapStyle::SquareCap"sv);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								template<>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								struct Formatter<PDF::LineJoinStyle> : Formatter<StringView> {
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-16 01:15:21 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ErrorOr<void> format(FormatBuilder& builder, PDF::LineJoinStyle const& style)
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        switch (style) {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        case PDF::LineJoinStyle::Miter:
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 20:23:24 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return builder.put_string("LineJoinStyle::Miter"sv);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        case PDF::LineJoinStyle::Round:
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 20:23:24 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return builder.put_string("LineJoinStyle::Round"sv);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        case PDF::LineJoinStyle::Bevel:
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 20:23:24 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return builder.put_string("LineJoinStyle::Bevel"sv);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								template<>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								struct Formatter<PDF::LineDashPattern> : Formatter<StringView> {
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-16 01:15:21 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ErrorOr<void> format(FormatBuilder& format_builder, PDF::LineDashPattern const& pattern)
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        StringBuilder builder;
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 20:10:18 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        builder.append('[');
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        bool first = true;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        for (auto& i : pattern.pattern) {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if (!first)
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                builder.append(", "sv);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            first = false;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            builder.appendff("{}", i);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        builder.appendff("] {}", pattern.phase);
							 | 
						
					
						
							
								
									
										
										
										
											2023-12-16 17:49:34 +03:30
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return format_builder.put_string(builder.to_byte_string());
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								template<>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								struct Formatter<PDF::TextRenderingMode> : Formatter<StringView> {
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-16 01:15:21 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ErrorOr<void> format(FormatBuilder& builder, PDF::TextRenderingMode const& style)
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        switch (style) {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        case PDF::TextRenderingMode::Fill:
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 20:23:24 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return builder.put_string("TextRenderingMode::Fill"sv);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        case PDF::TextRenderingMode::Stroke:
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 20:23:24 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return builder.put_string("TextRenderingMode::Stroke"sv);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        case PDF::TextRenderingMode::FillThenStroke:
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 20:23:24 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return builder.put_string("TextRenderingMode::FillThenStroke"sv);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        case PDF::TextRenderingMode::Invisible:
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 20:23:24 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return builder.put_string("TextRenderingMode::Invisible"sv);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        case PDF::TextRenderingMode::FillAndClip:
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 20:23:24 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return builder.put_string("TextRenderingMode::FillAndClip"sv);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        case PDF::TextRenderingMode::StrokeAndClip:
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 20:23:24 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return builder.put_string("TextRenderingMode::StrokeAndClip"sv);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        case PDF::TextRenderingMode::FillStrokeAndClip:
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 20:23:24 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return builder.put_string("TextRenderingMode::FillStrokeAndClip"sv);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        case PDF::TextRenderingMode::Clip:
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 20:23:24 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return builder.put_string("TextRenderingMode::Clip"sv);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								template<>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								struct Formatter<PDF::TextState> : Formatter<StringView> {
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-16 01:15:21 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ErrorOr<void> format(FormatBuilder& format_builder, PDF::TextState const& state)
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        StringBuilder builder;
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        builder.append("TextState {\n"sv);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        builder.appendff("    character_spacing={}\n", state.character_spacing);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        builder.appendff("    word_spacing={}\n", state.word_spacing);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        builder.appendff("    horizontal_scaling={}\n", state.horizontal_scaling);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        builder.appendff("    leading={}\n", state.leading);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-28 11:55:51 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        builder.appendff("    font_size={}\n", state.font_size);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        builder.appendff("    rendering_mode={}\n", state.rendering_mode);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        builder.appendff("    rise={}\n", state.rise);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        builder.appendff("    knockout={}\n", state.knockout);
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        builder.append(" }"sv);
							 | 
						
					
						
							
								
									
										
										
										
											2023-12-16 17:49:34 +03:30
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return format_builder.put_string(builder.to_byte_string());
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								template<>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								struct Formatter<PDF::GraphicsState> : Formatter<StringView> {
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-16 01:15:21 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ErrorOr<void> format(FormatBuilder& format_builder, PDF::GraphicsState const& state)
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        StringBuilder builder;
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 17:32:29 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        builder.append("GraphicsState {\n"sv);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        builder.appendff("  ctm={}\n", state.ctm);
							 | 
						
					
						
							
								
									
										
										
										
											2023-12-05 12:51:42 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if (state.stroke_style.has<Color>()) {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            builder.appendff("  stroke_style={}\n", state.stroke_style.get<Color>());
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        } else {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            builder.appendff("  stroke_style={}\n", state.stroke_style.get<NonnullRefPtr<Gfx::PaintStyle>>());
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if (state.paint_style.has<Color>()) {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            builder.appendff("  paint_style={}\n", state.paint_style.get<Color>());
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        } else {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            builder.appendff("  paint_style={}\n", state.paint_style.get<NonnullRefPtr<Gfx::PaintStyle>>());
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        }
							 | 
						
					
						
							
								
									
										
										
										
											2023-10-19 07:58:22 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        builder.appendff("  color_rendering_intent={}\n", state.color_rendering_intent);
							 | 
						
					
						
							
								
									
										
										
										
											2023-07-12 14:25:22 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        builder.appendff("  flatness_tolerance={}\n", state.flatness_tolerance);
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        builder.appendff("  line_width={}\n", state.line_width);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        builder.appendff("  line_cap_style={}\n", state.line_cap_style);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        builder.appendff("  line_join_style={}\n", state.line_join_style);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        builder.appendff("  miter_limit={}\n", state.miter_limit);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        builder.appendff("  line_dash_pattern={}\n", state.line_dash_pattern);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        builder.appendff("  text_state={}\n", state.text_state);
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 20:10:18 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        builder.append('}');
							 | 
						
					
						
							
								
									
										
										
										
											2023-12-16 17:49:34 +03:30
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return format_builder.put_string(builder.to_byte_string());
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-10 10:50:39 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								}
							 |