summaryrefslogtreecommitdiffstats
path: root/src/display/drawing-context.h
blob: ec488aca4b8bb9f8c6bf7629d004679bcef13c7e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// SPDX-License-Identifier: GPL-2.0-or-later
/**
 * @file
 * Cairo drawing context with Inkscape extensions.
 *//*
 * Authors:
 *   Krzysztof Kosiński <tweenk.pl@gmail.com>
 *
 * Copyright (C) 2011 Authors
 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
 */

#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_CONTEXT_H
#define SEEN_INKSCAPE_DISPLAY_DRAWING_CONTEXT_H

#include <2geom/rect.h>
#include <2geom/transforms.h>
#include <boost/utility.hpp>
#include <cairo.h>
typedef unsigned int guint32;

namespace Inkscape {

class DrawingSurface;

class DrawingContext
    : boost::noncopyable
{
public:
    class Save {
    public:
        Save();
        Save(DrawingContext &dc);
        ~Save();
        void save(DrawingContext &dc);
    private:
        DrawingContext *_dc;
    };

    DrawingContext(cairo_t *ct, Geom::Point const &origin);
    DrawingContext(cairo_surface_t *surface, Geom::Point const &origin);
    DrawingContext(DrawingSurface &s);
    ~DrawingContext();
    
    void save() { cairo_save(_ct); }
    void restore() { cairo_restore(_ct); }
    void pushGroup() { cairo_push_group(_ct); }
    void pushAlphaGroup() { cairo_push_group_with_content(_ct, CAIRO_CONTENT_ALPHA); }
    void popGroupToSource() { cairo_pop_group_to_source(_ct); }

    void transform(Geom::Affine const &trans);
    void translate(Geom::Point const &t) { cairo_translate(_ct, t[Geom::X], t[Geom::Y]); } // todo: take Translate
    void translate(double dx, double dy) { cairo_translate(_ct, dx, dy); }
    void scale(Geom::Scale const &s) { cairo_scale(_ct, s[Geom::X], s[Geom::Y]); }
    void scale(double sx, double sy) { cairo_scale(_ct, sx, sy); }
    void device_to_user_distance(double &dx, double &dy) { cairo_device_to_user_distance(_ct, &dx, &dy); }
    void user_to_device_distance(double &dx, double &dy) { cairo_user_to_device_distance(_ct, &dx, &dy); }

    void moveTo(Geom::Point const &p) { cairo_move_to(_ct, p[Geom::X], p[Geom::Y]); }
    void lineTo(Geom::Point const &p) { cairo_line_to(_ct, p[Geom::X], p[Geom::Y]); }
    void curveTo(Geom::Point const &p1, Geom::Point const &p2, Geom::Point const &p3) {
        cairo_curve_to(_ct, p1[Geom::X], p1[Geom::Y], p2[Geom::X], p2[Geom::Y], p3[Geom::X], p3[Geom::Y]);
    }
    void arc(Geom::Point const &center, double radius, Geom::AngleInterval const &angle);
    void closePath() { cairo_close_path(_ct); }
    void rectangle(Geom::Rect const &r) {
        cairo_rectangle(_ct, r.left(), r.top(), r.width(), r.height());
    }
    void rectangle(Geom::IntRect const &r) {
        cairo_rectangle(_ct, r.left(), r.top(), r.width(), r.height());
    }
    // Used in drawing-text.cpp to overwrite glyphs, which have the opposite path rotation as a regular rect
    void revrectangle(Geom::Rect const &r) {
        cairo_move_to (    _ct, r.left(), r.top()      );
        cairo_rel_line_to (_ct, 0,        r.height()   );
        cairo_rel_line_to (_ct,           r.width(), 0 );
        cairo_rel_line_to (_ct, 0,       -r.height()   );
        cairo_close_path ( _ct);
    }
    void revrectangle(Geom::IntRect const &r) {
        cairo_move_to (    _ct, r.left(), r.top()      );
        cairo_rel_line_to (_ct, 0,        r.height()   );
        cairo_rel_line_to (_ct,           r.width(), 0 );
        cairo_rel_line_to (_ct, 0,       -r.height()   );
        cairo_close_path ( _ct);
    }
    void newPath() { cairo_new_path(_ct); }
    void newSubpath() { cairo_new_sub_path(_ct); }
    void path(Geom::PathVector const &pv);

    void paint(double alpha = 1.0);
    void fill() { cairo_fill(_ct); }
    void fillPreserve() { cairo_fill_preserve(_ct); }
    void stroke() { cairo_stroke(_ct); }
    void strokePreserve() { cairo_stroke_preserve(_ct); }
    void clip() { cairo_clip(_ct); }

    void setLineWidth(double w) { cairo_set_line_width(_ct, w); }
    void setHairline();
    void setLineCap(cairo_line_cap_t cap) { cairo_set_line_cap(_ct, cap); }
    void setLineJoin(cairo_line_join_t join) { cairo_set_line_join(_ct, join); }
    void setMiterLimit(double miter) { cairo_set_miter_limit(_ct, miter); }
    void setFillRule(cairo_fill_rule_t rule) { cairo_set_fill_rule(_ct, rule); }
    void setOperator(cairo_operator_t op) { cairo_set_operator(_ct, op); }
    cairo_operator_t getOperator() { return cairo_get_operator(_ct); }
    void setTolerance(double tol) { cairo_set_tolerance(_ct, tol); }
    void setSource(cairo_pattern_t *source) { cairo_set_source(_ct, source); }
    void setSource(cairo_surface_t *surface, double x, double y) {
        cairo_set_source_surface(_ct, surface, x, y);
    }
    void setSource(double r, double g, double b, double a = 1.0) {
        cairo_set_source_rgba(_ct, r, g, b, a);
    }
    void setSource(guint32 rgba);
    void setSource(DrawingSurface *s);

    void patternSetFilter(cairo_filter_t filter) {
        cairo_pattern_set_filter(cairo_get_source(_ct), filter);
    }
    void patternSetExtend(cairo_extend_t extend) { cairo_pattern_set_extend(cairo_get_source(_ct), extend); }

    Geom::Rect targetLogicalBounds() const;

    cairo_t *raw() { return _ct; }
    cairo_surface_t *rawTarget() { return cairo_get_group_target(_ct); }

    DrawingSurface *surface() { return _surface; } // Needed to find scale in drawing-item.cpp

private:
    DrawingContext(cairo_t *ct, DrawingSurface *surface, bool destroy);

    cairo_t *_ct;
    DrawingSurface *_surface;
    bool _delete_surface;
    bool _restore_context;

    friend class DrawingSurface;
};

} // end namespace Inkscape

#endif // !SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H

/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :