From cca66b9ec4e494c1d919bff0f71a820d8afab1fa Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:24:48 +0200 Subject: Adding upstream version 1.2.2. Signed-off-by: Daniel Baumann --- src/ui/widget/page-size-preview.cpp | 185 ++++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 src/ui/widget/page-size-preview.cpp (limited to 'src/ui/widget/page-size-preview.cpp') diff --git a/src/ui/widget/page-size-preview.cpp b/src/ui/widget/page-size-preview.cpp new file mode 100644 index 0000000..40e2ea5 --- /dev/null +++ b/src/ui/widget/page-size-preview.cpp @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** + * @file + * + * Page size preview widget + */ +/* + * Authors: + * Mike Kowalski + * + * Copyright (C) 2021 Authors + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include "page-size-preview.h" +#include "display/cairo-utils.h" +#include "2geom/rect.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +PageSizePreview::PageSizePreview() { + show(); +} + +void rounded_rectangle(const Cairo::RefPtr& cr, double x, double y, double w, double h, double r) { + cr->begin_new_sub_path(); + cr->arc(x + r, y + r, r, M_PI, 3 * M_PI / 2); + cr->arc(x + w - r, y + r, r, 3 * M_PI / 2, 2 * M_PI); + cr->arc(x + w - r, y + h - r, r, 0, M_PI / 2); + cr->arc(x + r, y + h - r, r, M_PI / 2, M_PI); + cr->close_path(); +} + +void set_source_rgba(const Cairo::RefPtr& ctx, unsigned int rgba) { + ctx->set_source_rgba(SP_RGBA32_R_F(rgba), SP_RGBA32_G_F(rgba), SP_RGBA32_B_F(rgba), SP_RGBA32_A_F(rgba)); +} + +bool PageSizePreview::on_draw(const Cairo::RefPtr& ctx) { + auto alloc = get_allocation(); + double width = alloc.get_width(); + double height = alloc.get_height(); + // too small to fit anything? + if (width <= 2 || height <= 2) return false; + + double x = 0;//alloc.get_x(); + double y = 0;//alloc.get_y(); + + if (_draw_checkerboard) { + // auto device_scale = get_scale_factor(); + Cairo::RefPtr pattern(new Cairo::Pattern(ink_cairo_pattern_create_checkerboard(_desk_color))); + ctx->save(); + ctx->set_operator(Cairo::OPERATOR_SOURCE); + ctx->set_source(pattern); + rounded_rectangle(ctx, x, y, width, height, 2.0); + ctx->fill(); + ctx->restore(); + } + else { + rounded_rectangle(ctx, x, y, width, height, 2.0); + set_source_rgba(ctx, _desk_color); + ctx->fill(); + } + + // use lesser dimension to prevent page from changing size when + // switching from portrait to landscape or vice versa + auto size = std::round(std::min(width, height) * 0.90); // 90% to leave margins + double w, h; + if (_width > _height) { + w = size; + h = std::round(size * _height / _width); + } + else { + h = size; + w = std::round(size * _width / _height); + } + if (w < 2) w = 2; + if (h < 2) h = 2; + + // center page + double ox = std::round(x + (width - w) / 2); + double oy = std::round(y + (height - h) / 2); + Geom::Rect rect(ox, oy, ox + w, oy + h); + + ctx->rectangle(rect.left(), rect.top(), rect.width(), rect.height()); + + if (_draw_checkerboard) { + Cairo::RefPtr pattern(new Cairo::Pattern(ink_cairo_pattern_create_checkerboard(_page_color))); + ctx->save(); + ctx->set_operator(Cairo::OPERATOR_SOURCE); + ctx->set_source(pattern); + ctx->rectangle(rect.left(), rect.top(), rect.width(), rect.height()); + ctx->fill(); + ctx->restore(); + } + else { + ctx->rectangle(rect.left(), rect.top(), rect.width(), rect.height()); + set_source_rgba(ctx, _page_color | 0xff); + ctx->fill(); + } + + // draw cross + { + double gradient_size = 4; + double cx = std::round(x + (width - gradient_size) / 2); + double cy = std::round(y + (height - gradient_size) / 2); + auto horz = Cairo::LinearGradient::create(x, cy, x, cy + gradient_size); + auto vert = Cairo::LinearGradient::create(cx, y, cx + gradient_size, y); + + horz->add_color_stop_rgba(0.0, 0, 0, 0, 0.0); + horz->add_color_stop_rgba(0.5, 0, 0, 0, 0.2); + horz->add_color_stop_rgba(0.5, 1, 1, 1, 0.8); + horz->add_color_stop_rgba(1.0, 1, 1, 1, 0.0); + + vert->add_color_stop_rgba(0.0, 0, 0, 0, 0.0); + vert->add_color_stop_rgba(0.5, 0, 0, 0, 0.2); + vert->add_color_stop_rgba(0.5, 1, 1, 1, 0.8); + vert->add_color_stop_rgba(1.0, 1, 1, 1, 0.0); + + ctx->rectangle(x, cy, width, gradient_size); + ctx->set_source(horz); + ctx->fill(); + + ctx->rectangle(cx, y, gradient_size, height); + ctx->set_source(vert); + ctx->fill(); + } + + ctx->rectangle(rect.left(), rect.top(), rect.width(), rect.height()); + set_source_rgba(ctx, _page_color); + ctx->fill(); + + if (_draw_border) { + // stoke; not pixel aligned, just like page on canvas + ctx->rectangle(rect.left(), rect.top(), rect.width(), rect.height()); + set_source_rgba(ctx, _border_color); + ctx->set_line_width(1); + ctx->stroke(); + + if (_draw_shadow) { + const auto a = (exp(-3 * SP_RGBA32_A_F(_border_color)) - 1) / (exp(-3) - 1); + ink_cairo_draw_drop_shadow(ctx, rect, 12, _border_color, a); + } + } + + return true; +} + +void PageSizePreview::draw_border(bool border) { + _draw_border = border; + queue_draw(); +} + +void PageSizePreview::set_desk_color(unsigned int rgba) { + _desk_color = rgba | 0xff; // desk always opaque + queue_draw(); +} +void PageSizePreview::set_page_color(unsigned int rgba) { + _page_color = rgba; + queue_draw(); +} +void PageSizePreview::set_border_color(unsigned int rgba) { + _border_color = rgba; + queue_draw(); +} + +void PageSizePreview::enable_drop_shadow(bool shadow) { + _draw_shadow = shadow; + queue_draw(); +} + +void PageSizePreview::enable_checkerboard(bool checkerboard) { + _draw_checkerboard = checkerboard; + queue_draw(); +} + +void PageSizePreview::set_page_size(double width, double height) { + _width = width; + _height = height; + queue_draw(); +} + +} } } // namespace Inkscape/Widget/UI -- cgit v1.2.3