mirror of
https://github.com/SerenityOS/serenity.git
synced 2026-11-07 04:29:30 -10:00
LibPDF: Extract common_entries() in Pattern.cpp
No behavior change.
This commit is contained in:
1 parent
dddae788ab
commit
95b0add504
1 file changed
+47
-37
@@ -13,6 +13,47 @@
|
||||
|
||||
namespace PDF {
|
||||
|
||||
namespace {
|
||||
|
||||
// Entries present in both:
|
||||
// TABLE 4.25 Additional entries specific to a type 1 pattern dictionary
|
||||
// TABLE 4.26 Entries in a type 2 pattern dictionary
|
||||
struct CommonEntries {
|
||||
// "(Optional) An array of six numbers specifying the pattern matrix (see Section
|
||||
// 4.6.1, “General Properties of Patterns”). Default value: the identity matrix
|
||||
// [ 1 0 0 1 0 0 ]."
|
||||
Gfx::AffineTransform matrix { 1, 0, 0, 1, 0, 0 };
|
||||
};
|
||||
|
||||
PDFErrorOr<CommonEntries> read_common_entries(Document* document, DictObject const& pattern_dict)
|
||||
{
|
||||
// "Type (Optional) The type of PDF object that this dictionary describes;
|
||||
// if present, shall be Pattern for a pattern dictionary.""
|
||||
auto const type = pattern_dict.get(CommonNames::Type);
|
||||
if (type.has_value()) {
|
||||
auto type_name = type->get<NonnullRefPtr<Object>>()->cast<NameObject>();
|
||||
if (type_name->name() != CommonNames::Pattern)
|
||||
return Error::rendering_unsupported_error("Unsupported pattern type {}", type_name->name());
|
||||
}
|
||||
|
||||
CommonEntries common_entries;
|
||||
|
||||
if (pattern_dict.contains(CommonNames::Matrix)) {
|
||||
auto pattern_matrix = pattern_dict.get_array(document, CommonNames::Matrix).value()->elements();
|
||||
common_entries.matrix = Gfx::AffineTransform(
|
||||
pattern_matrix[0].to_float(),
|
||||
pattern_matrix[1].to_float(),
|
||||
pattern_matrix[2].to_float(),
|
||||
pattern_matrix[3].to_float(),
|
||||
pattern_matrix[4].to_float(),
|
||||
pattern_matrix[5].to_float());
|
||||
}
|
||||
|
||||
return common_entries;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PDFErrorOr<ColorOrStyle> Pattern::style(Document*, NonnullRefPtr<Object> pattern, Renderer& renderer)
|
||||
{
|
||||
NonnullRefPtr<DictObject> pattern_dict = [&] {
|
||||
@@ -22,52 +63,19 @@ PDFErrorOr<ColorOrStyle> Pattern::style(Document*, NonnullRefPtr<Object> pattern
|
||||
return pattern->cast<StreamObject>()->dict();
|
||||
}();
|
||||
|
||||
// PDF 1.7 spec, 4.6 Patterns
|
||||
// TABLE 4.25 Additional entries specific to a type 1 pattern dictionary
|
||||
// TABLE 4.26 Entries in a type 2 pattern dictionary
|
||||
// Both have:
|
||||
// - /Type (optional)
|
||||
// - /PatternType (required)
|
||||
// - /Matrix (optional)
|
||||
// The other entries are specific to the pattern type.
|
||||
|
||||
// PatternType (Required) A code identifying the type of pattern that this dictionary describes;
|
||||
// shall be 1 for a tiling pattern
|
||||
auto const pattern_type = pattern_dict->get(CommonNames::PatternType)->get_u16();
|
||||
if (pattern_type != 1)
|
||||
return Error::rendering_unsupported_error("Unsupported pattern type {}", pattern_type);
|
||||
|
||||
// Type (Optional) The type of PDF object that this dictionary describes;
|
||||
// if present, shall be Pattern for a pattern dictionary
|
||||
auto const type = pattern_dict->get(CommonNames::Type);
|
||||
if (type.has_value()) {
|
||||
auto type_name = type->get<NonnullRefPtr<Object>>()->cast<NameObject>();
|
||||
if (type_name->name() != CommonNames::Pattern)
|
||||
return Error::rendering_unsupported_error("Unsupported pattern type {}", type_name->name());
|
||||
}
|
||||
auto common_entries = TRY(read_common_entries(renderer.m_document, *pattern_dict));
|
||||
|
||||
// PaintType (Required) A code that determines how the colour of the pattern cell shall be specified
|
||||
auto const pattern_paint_type = pattern_dict->get("PaintType")->get_u16();
|
||||
if (pattern_paint_type != 1)
|
||||
return Error::rendering_unsupported_error("Unsupported pattern paint type {}", pattern_paint_type);
|
||||
|
||||
// Matrix (Optional) An array of six numbers specifying the pattern matrix
|
||||
Vector<Value> pattern_matrix;
|
||||
if (pattern_dict->contains(CommonNames::Matrix)) {
|
||||
pattern_matrix = pattern_dict->get_array(renderer.m_document, CommonNames::Matrix).value()->elements();
|
||||
} else {
|
||||
pattern_matrix = Vector { Value { 1 }, Value { 0 }, Value { 0 }, Value { 1 }, Value { 0 }, Value { 0 } };
|
||||
}
|
||||
|
||||
auto pattern_bounding_box = pattern_dict->get_array(renderer.m_document, "BBox").value()->elements();
|
||||
auto pattern_transform = Gfx::AffineTransform(
|
||||
pattern_matrix[0].to_float(),
|
||||
pattern_matrix[1].to_float(),
|
||||
pattern_matrix[2].to_float(),
|
||||
pattern_matrix[3].to_float(),
|
||||
pattern_matrix[4].to_float(),
|
||||
pattern_matrix[5].to_float());
|
||||
|
||||
// To get the device space size for the bitmap, apply the pattern transform to the pattern space bounding box, and then apply the initial ctm.
|
||||
// NB: the pattern pattern_matrix maps pattern space to the default (initial) coordinate space of the page. (i.e cannot be updated via cm).
|
||||
|
||||
@@ -75,11 +83,13 @@ PDFErrorOr<ColorOrStyle> Pattern::style(Document*, NonnullRefPtr<Object> pattern
|
||||
initial_ctm.set_translation(0, 0);
|
||||
initial_ctm.set_scale(initial_ctm.x_scale(), initial_ctm.y_scale());
|
||||
|
||||
auto pattern_bounding_box = pattern_dict->get_array(renderer.m_document, "BBox").value()->elements();
|
||||
|
||||
auto pattern_space_lower_left = Gfx::FloatPoint { pattern_bounding_box[0].to_int(), pattern_bounding_box[1].to_int() };
|
||||
auto pattern_space_upper_right = Gfx::FloatPoint { pattern_bounding_box[2].to_int(), pattern_bounding_box[3].to_int() };
|
||||
|
||||
auto device_space_lower_left = initial_ctm.map(pattern_transform.map(pattern_space_lower_left));
|
||||
auto device_space_upper_right = initial_ctm.map(pattern_transform.map(pattern_space_upper_right));
|
||||
auto device_space_lower_left = initial_ctm.map(common_entries.matrix.map(pattern_space_lower_left));
|
||||
auto device_space_upper_right = initial_ctm.map(common_entries.matrix.map(pattern_space_upper_right));
|
||||
|
||||
auto bitmap_width = abs((int)device_space_upper_right.x() - (int)device_space_lower_left.x());
|
||||
auto bitmap_height = abs((int)device_space_upper_right.y() - (int)device_space_lower_left.y());
|
||||
@@ -106,7 +116,7 @@ PDFErrorOr<ColorOrStyle> Pattern::style(Document*, NonnullRefPtr<Object> pattern
|
||||
auto x_steps = pattern_dict->get("XStep").value_or(bitmap_width).to_int();
|
||||
auto y_steps = pattern_dict->get("YStep").value_or(bitmap_height).to_int();
|
||||
|
||||
auto device_space_steps = initial_ctm.map(pattern_transform.map(Gfx::IntPoint { x_steps, y_steps }));
|
||||
auto device_space_steps = initial_ctm.map(common_entries.matrix.map(Gfx::IntPoint { x_steps, y_steps }));
|
||||
|
||||
NonnullRefPtr<Gfx::PaintStyle> style = MUST(Gfx::RepeatingBitmapPaintStyle::create(
|
||||
*pattern_cell,
|
||||
|
||||
Reference in new issue
Block a user