File indexing completed on 2024-05-12 09:52:48
0001 /***************************************************************************** 0002 * Copyright 2003 - 2010 Craig Drummond <craig.p.drummond@gmail.com> * 0003 * Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com> * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU Lesser General Public License as * 0007 * published by the Free Software Foundation; either version 2.1 of the * 0008 * License, or (at your option) version 3, or any later version accepted * 0009 * by the membership of KDE e.V. (or its successor approved by the * 0010 * membership of KDE e.V.), which shall act as a proxy defined in * 0011 * Section 6 of version 3 of the license. * 0012 * * 0013 * This program is distributed in the hope that it will be useful, * 0014 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 0016 * Lesser General Public License for more details. * 0017 * * 0018 * You should have received a copy of the GNU Lesser General Public * 0019 * License along with this library. If not, * 0020 * see <http://www.gnu.org/licenses/>. * 0021 *****************************************************************************/ 0022 0023 #include "draw.h" 0024 #include "utils_p.h" 0025 #include <pango/pangocairo.h> 0026 0027 namespace QtCurve { 0028 namespace Cairo { 0029 0030 QTC_EXPORT void 0031 hLine(cairo_t *cr, int x, int y, int w, const GdkColor *col, double a) 0032 { 0033 Saver saver(cr); 0034 cairo_new_path(cr); 0035 setColor(cr, col, a); 0036 cairo_move_to(cr, x, y + 0.5); 0037 cairo_line_to(cr, x + w, y + 0.5); 0038 cairo_stroke(cr); 0039 } 0040 0041 QTC_EXPORT void 0042 vLine(cairo_t *cr, int x, int y, int h, const GdkColor *col, double a) 0043 { 0044 Saver saver(cr); 0045 cairo_new_path(cr); 0046 setColor(cr, col, a); 0047 cairo_move_to(cr, x + 0.5, y); 0048 cairo_line_to(cr, x + 0.5, y + h); 0049 cairo_stroke(cr); 0050 } 0051 0052 QTC_EXPORT void 0053 polygon(cairo_t *cr, const GdkColor *col, const QtcRect *area, 0054 const GdkPoint *points, int npoints, bool fill) 0055 { 0056 Saver saver(cr); 0057 cairo_set_line_width(cr, 1); 0058 clipRect(cr, area); 0059 setColor(cr, col); 0060 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); 0061 pathPoints(cr, points, npoints); 0062 cairo_close_path(cr); 0063 cairo_stroke_preserve(cr); 0064 if (fill) { 0065 cairo_fill(cr); 0066 } 0067 } 0068 0069 QTC_EXPORT void 0070 rect(cairo_t *cr, const QtcRect *area, int x, int y, int width, int height, 0071 const GdkColor *col, double alpha) 0072 { 0073 Saver saver(cr); 0074 clipRect(cr, area); 0075 cairo_rectangle(cr, x, y, width, height); 0076 setColor(cr, col, alpha); 0077 cairo_fill(cr); 0078 } 0079 0080 QTC_EXPORT void 0081 fadedLine(cairo_t *cr, int x, int y, int width, int height, 0082 const QtcRect *area, const QtcRect *gap, bool fadeStart, 0083 bool fadeEnd, double fadeSize, bool horiz, 0084 const GdkColor *col, double alpha) 0085 { 0086 double rx = x + 0.5; 0087 double ry = y + 0.5; 0088 cairo_pattern_t *pt = 0089 cairo_pattern_create_linear(rx, ry, horiz ? rx + width - 1 : rx + 1, 0090 horiz ? ry + 1 : ry + height - 1); 0091 0092 Saver saver(cr); 0093 if (gap) { 0094 QtcRect r = {x, y, width, height}; 0095 cairo_region_t *region = 0096 cairo_region_create_rectangle(area ? area : &r); 0097 cairo_region_xor_rectangle(region, gap); 0098 clipRegion(cr, region); 0099 cairo_region_destroy(region); 0100 } else { 0101 clipRect(cr, area); 0102 } 0103 patternAddColorStop(pt, 0, col, fadeStart ? 0.0 : alpha); 0104 patternAddColorStop(pt, fadeSize, col, alpha); 0105 patternAddColorStop(pt, 1 - fadeSize, col, alpha); 0106 patternAddColorStop(pt, 1, col, fadeEnd ? 0.0 : alpha); 0107 cairo_set_source(cr, pt); 0108 if (horiz) { 0109 cairo_move_to(cr, x, ry); 0110 cairo_line_to(cr, x + width - 1, ry); 0111 } else { 0112 cairo_move_to(cr, rx, y); 0113 cairo_line_to(cr, rx, y + height - 1); 0114 } 0115 cairo_stroke(cr); 0116 cairo_pattern_destroy(pt); 0117 } 0118 0119 QTC_EXPORT void 0120 stripes(cairo_t *cr, int x, int y, int w, int h, 0121 bool horizontal, int stripeWidth) 0122 { 0123 int endx = horizontal ? stripeWidth : 0; 0124 int endy = horizontal ? 0 : stripeWidth; 0125 cairo_pattern_t *pat = 0126 cairo_pattern_create_linear(x, y, x + endx, y + endy); 0127 cairo_pattern_add_color_stop_rgba(pat, 0.0, 1.0, 1.0, 1.0, 0.0); 0128 cairo_pattern_add_color_stop_rgba(pat, 1, 1.0, 1.0, 1.0, 0.15); 0129 cairo_pattern_set_extend(pat, CAIRO_EXTEND_REFLECT); 0130 0131 Saver saver(cr); 0132 cairo_set_source(cr, pat); 0133 cairo_rectangle(cr, x, y, w, h); 0134 cairo_fill(cr); 0135 0136 cairo_pattern_destroy(pat); 0137 } 0138 0139 QTC_EXPORT void 0140 dot(cairo_t *cr, int x, int y, int w, int h, const GdkColor *col) 0141 { 0142 double dx = x + (w - 5) / 2; 0143 double dy = y + (h - 5) / 2; 0144 cairo_pattern_t *p1 = cairo_pattern_create_linear(dx, dy, dx + 4, dy + 4); 0145 cairo_pattern_t *p2 = cairo_pattern_create_linear(dx + 2, dy + 2, 0146 dx + 4, dx + 4); 0147 0148 patternAddColorStop(p1, 0, col, 1); 0149 patternAddColorStop(p1, 1, col, 0.4); 0150 cairo_pattern_add_color_stop_rgba(p2, 1, 1, 1, 1, 0.9); 0151 cairo_pattern_add_color_stop_rgba(p2, 0, 1, 1, 1, 0.7); 0152 0153 Saver saver(cr); 0154 cairo_new_path(cr); 0155 cairo_arc(cr, dx + 2.5, dy + 2.5, 2.5, 0, 2 * M_PI); 0156 cairo_clip(cr); 0157 cairo_set_source(cr, p1); 0158 cairo_rectangle(cr, dx, dy, 5, 5); 0159 cairo_fill(cr); 0160 0161 cairo_new_path(cr); 0162 cairo_arc(cr, dx + 3, dy + 3, 2, 0, 2 * M_PI); 0163 cairo_clip(cr); 0164 cairo_set_source(cr, p2); 0165 cairo_rectangle(cr, dx + 1, dy + 1, 4, 4); 0166 cairo_fill(cr); 0167 0168 cairo_pattern_destroy(p1); 0169 cairo_pattern_destroy(p2); 0170 } 0171 0172 QTC_EXPORT void 0173 dots(cairo_t *cr, int rx, int ry, int rwidth, int rheight, bool horiz, 0174 int nLines, int offset, const QtcRect *area, int startOffset, 0175 const GdkColor *col1, const GdkColor *col2) 0176 { 0177 int space = nLines * 2 + nLines - 1; 0178 int x = horiz ? rx : rx + (rwidth - space) / 2; 0179 int y = horiz ? ry + (rheight - space) / 2 : ry; 0180 int numDots = ((horiz ? rwidth : rheight) - 2 * offset) / 3 + 1; 0181 0182 Saver saver(cr); 0183 clipRect(cr, area); 0184 if (horiz) { 0185 if (startOffset && y + startOffset > 0) { 0186 y += startOffset; 0187 } 0188 cairo_new_path(cr); 0189 setColor(cr, col1); 0190 for (int i = 0;i < space;i += 3) { 0191 for (int j = 0;j < numDots;j++) { 0192 cairo_rectangle(cr, x + offset + 3 * j, y + i, 1, 1); 0193 } 0194 } 0195 cairo_fill(cr); 0196 0197 cairo_new_path(cr); 0198 setColor(cr, col2); 0199 for (int i = 1;i < space;i += 3) { 0200 for (int j = 0;j < numDots;j++) { 0201 cairo_rectangle(cr, x + offset + 1 + 3 * j, y + i, 1, 1); 0202 } 0203 } 0204 cairo_fill(cr); 0205 } else { 0206 if (startOffset && x + startOffset > 0) { 0207 x += startOffset; 0208 } 0209 cairo_new_path(cr); 0210 setColor(cr, col1); 0211 for (int i = 0;i < space;i += 3) { 0212 for (int j = 0;j < numDots;j++) { 0213 cairo_rectangle(cr, x + i, y + offset + 3 * j, 1, 1); 0214 } 0215 } 0216 cairo_fill(cr); 0217 0218 cairo_new_path(cr); 0219 setColor(cr, col2); 0220 for (int i = 1;i < space;i += 3) { 0221 for(int j = 0;j < numDots;j++) { 0222 cairo_rectangle(cr, x + i, y + offset + 1 + 3 * j, 1, 1); 0223 } 0224 } 0225 cairo_fill(cr); 0226 } 0227 } 0228 0229 static void 0230 ge_transform_for_layout(cairo_t *cr, PangoLayout *layout, int x, int y) 0231 { 0232 const PangoMatrix *matrix = 0233 pango_context_get_matrix(pango_layout_get_context(layout)); 0234 if (matrix) { 0235 cairo_matrix_t cairo_matrix; 0236 PangoRectangle _rect; 0237 0238 cairo_matrix_init(&cairo_matrix, matrix->xx, matrix->yx, 0239 matrix->xy, matrix->yy, matrix->x0, matrix->y0); 0240 pango_layout_get_extents(layout, nullptr, &_rect); 0241 pango_matrix_transform_rectangle(matrix, &_rect); 0242 pango_extents_to_pixels(&_rect, nullptr); 0243 0244 cairo_matrix.x0 += x - _rect.x; 0245 cairo_matrix.y0 += y - _rect.y; 0246 0247 cairo_set_matrix(cr, &cairo_matrix); 0248 } else { 0249 cairo_translate(cr, x, y); 0250 } 0251 } 0252 0253 QTC_EXPORT void 0254 layout(cairo_t *cr, const QtcRect *area, int x, int y, PangoLayout *_layout, 0255 const GdkColor *col) 0256 { 0257 Saver saver(cr); 0258 clipRect(cr, area); 0259 cairo_set_line_width(cr, 1); 0260 setColor(cr, col); 0261 ge_transform_for_layout(cr, _layout, x, y); 0262 pango_cairo_show_layout(cr, _layout); 0263 } 0264 0265 QTC_EXPORT void 0266 arrow(cairo_t *cr, const GdkColor *col, const QtcRect *area, 0267 ArrowType arrow_type, int x, int y, bool small, bool fill, bool varrow) 0268 { 0269 if (small) { 0270 switch (arrow_type) { 0271 case ArrowType::Up: { 0272 const GdkPoint a[] = {{x + 2, y}, {x, y - 2}, {x - 2, y}, 0273 {x - 2, y + 1}, {x, y - 1}, {x + 2, y + 1}}; 0274 polygon(cr, col, area, a, varrow ? 6 : 3, fill); 0275 break; 0276 } 0277 case ArrowType::Down: { 0278 const GdkPoint a[] = {{x + 2, y}, {x, y + 2}, {x - 2, y}, 0279 {x - 2, y - 1}, {x, y + 1}, {x + 2, y - 1}}; 0280 polygon(cr, col, area, a, varrow ? 6 : 3, fill); 0281 break; 0282 } 0283 case ArrowType::Right: { 0284 const GdkPoint a[] = {{x, y - 2}, {x + 2, y}, {x, y + 2}, 0285 {x - 1, y + 2}, {x + 1, y}, {x - 1, y - 2}}; 0286 polygon(cr, col, area, a, varrow ? 6 : 3, fill); 0287 break; 0288 } 0289 case ArrowType::Left: { 0290 const GdkPoint a[] = {{x, y - 2}, {x - 2, y}, {x, y + 2}, 0291 {x + 1, y + 2}, {x - 1, y}, {x + 1, y - 2}}; 0292 polygon(cr, col, area, a, varrow ? 6 : 3, fill); 0293 break; 0294 } 0295 default: 0296 break; 0297 } 0298 } else { 0299 /* Large arrows... */ 0300 switch (arrow_type) { 0301 case ArrowType::Up: { 0302 const GdkPoint a[] = {{x + 3, y + 1}, {x, y - 2}, {x - 3, y + 1}, 0303 {x - 3, y + 2}, {x - 2, y + 2}, {x, y}, 0304 {x + 2, y + 2}, {x + 3, y + 2}}; 0305 polygon(cr, col, area, a, varrow ? 8 : 3, fill); 0306 break; 0307 } 0308 case ArrowType::Down: { 0309 const GdkPoint a[] = {{x + 3, y - 1}, {x, y + 2}, {x - 3, y - 1}, 0310 {x - 3, y - 2}, {x - 2, y - 2}, {x, y}, 0311 {x + 2, y - 2}, {x + 3,y - 2}}; 0312 polygon(cr, col, area, a, varrow ? 8 : 3, fill); 0313 break; 0314 } 0315 case ArrowType::Right: { 0316 const GdkPoint a[] = {{x - 1, y + 3}, {x + 2, y}, {x - 1, y - 3}, 0317 {x - 2, y - 3}, {x - 2, y - 2}, {x, y}, 0318 {x - 2, y + 2}, {x - 2, y + 3}}; 0319 polygon(cr, col, area, a, varrow ? 8 : 3, fill); 0320 break; 0321 } 0322 case ArrowType::Left: { 0323 const GdkPoint a[] = {{x + 1, y - 3}, {x - 2, y}, {x + 1, y + 3}, 0324 {x + 2, y + 3}, {x + 2, y + 2}, {x, y}, 0325 {x + 2, y - 2}, {x + 2, y - 3}}; 0326 polygon(cr, col, area, a, varrow ? 8 : 3, fill); 0327 break; 0328 } 0329 default: 0330 break; 0331 } 0332 } 0333 } 0334 0335 } 0336 }