1 /** 2 * This module contains wrappers for most of cairo's fuctionality. 3 * Additional wrappers for subsets of cairo are available in the 4 * cairo.* modules. 5 * 6 * Note: 7 * Most cairoD functions could throw an OutOfMemoryError. This is therefore not 8 * explicitly stated in the functions' api documenation. 9 * 10 * See_Also: 11 * $(LINK http://cairographics.org/documentation/) 12 * 13 * License: 14 * $(TABLE 15 * $(TR $(TD cairoD wrapper/bindings) 16 * $(TD $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0))) 17 * $(TR $(TD $(LINK2 http://cgit.freedesktop.org/cairo/tree/COPYING, _cairo)) 18 * $(TD $(LINK2 http://cgit.freedesktop.org/cairo/tree/COPYING-LGPL-2.1, LGPL 2.1) / 19 * $(LINK2 http://cgit.freedesktop.org/cairo/plain/COPYING-MPL-1.1, MPL 1.1))) 20 * ) 21 * Authors: 22 * $(TABLE 23 * $(TR $(TD Johannes Pfau) $(TD cairoD)) 24 * $(TR $(TD Andrej Mitrovic) $(TD cairoD)) 25 * $(TR $(TD $(LINK2 http://cairographics.org, _cairo team)) $(TD _cairo)) 26 * ) 27 */ 28 /* 29 * Distributed under the Boost Software License, Version 1.0. 30 * (See accompanying file LICENSE_1_0.txt or copy at 31 * http://www.boost.org/LICENSE_1_0.txt) 32 */ 33 module cairo.cairo; 34 35 import cairo.c.cairo; 36 import cairo.util; 37 38 import core.exception; 39 import std.algorithm; 40 import std.conv; 41 import std.format : formattedWrite; 42 import std.string; 43 import std.traits; 44 import std.typecons; 45 46 debug(RefCounted) 47 { 48 import std.stdio; 49 } 50 51 /** 52 * Mainly used internally by cairoD. 53 * If status is CAIRO_STATUS_NO_MEMORY a OutOfMemoryError is thrown. 54 * If status is CAIRO_STATUS_SUCCESS nothing happens. 55 * For all other statuses, this functions throws 56 * a $(D CairoException) with the status value. 57 */ 58 void throwError(cairo_status_t status, string file = __FILE__, int line = __LINE__) 59 { 60 switch(status) 61 { 62 case cairo_status_t.CAIRO_STATUS_SUCCESS: 63 return; 64 case cairo_status_t.CAIRO_STATUS_NO_MEMORY: 65 throw new OutOfMemoryError(file, line); 66 default: 67 throw new CairoException(status, file, line); 68 } 69 } 70 71 /** 72 * Convert a size_t as given from a D arrays .length property 73 * to a cairo count type (int). 74 * 75 * In debug mode an exception is thrown if the size_t value does 76 * not fit into the int type. In release mode all checks are 77 * removed! 78 */ 79 private int toCairoCount(size_t length) 80 { 81 debug 82 { 83 import std.conv; 84 return to!int(length); 85 } 86 else 87 { 88 return cast(int)length; 89 } 90 } 91 92 unittest 93 { 94 assert(toCairoCount(int.max) == int.max); 95 assert(toCairoCount(0) == 0); 96 assert(toCairoCount(42) == 42); 97 debug 98 { 99 import std.exception; 100 assertThrown(toCairoCount(int.max + 1)); 101 } 102 } 103 104 /** 105 * Exception thrown by cairoD if an error occurs. 106 */ 107 public class CairoException : Exception 108 { 109 public: 110 /** 111 * Cairo's error status. 112 * Gives further information about the error. 113 */ 114 cairo_status_t status; 115 116 /// 117 this(cairo_status_t stat, string file = __FILE__, int line = __LINE__) 118 { 119 this.status = stat; 120 super(format("%s: %s", this.status, to!string(cairo_status_to_string(this.status)))); 121 } 122 } 123 124 /** 125 * Aliases for simple cairo enums and structs. 126 * Theses aliases provide D-like names when 127 * using the cairoD API. 128 */ 129 public alias cairo_content_t Content; 130 public alias cairo_antialias_t AntiAlias; ///ditto 131 public alias cairo_subpixel_order_t SubpixelOrder; ///ditto 132 public alias cairo_hint_style_t HintStyle; ///ditto 133 public alias cairo_hint_metrics_t HintMetrics; ///ditto 134 public alias cairo_surface_type_t SurfaceType; ///ditto 135 public alias cairo_format_t Format; ///ditto 136 public alias cairo_extend_t Extend; ///ditto 137 public alias cairo_filter_t Filter; ///ditto 138 public alias cairo_pattern_type_t PatternType; ///ditto 139 public alias cairo_fill_rule_t FillRule; ///ditto 140 public alias cairo_line_cap_t LineCap; ///ditto 141 public alias cairo_line_join_t LineJoin; ///ditto 142 public alias cairo_operator_t Operator; ///ditto 143 public alias cairo_path_data_type_t PathElementType; ///ditto 144 public alias cairo_font_extents_t FontExtents; ///ditto 145 public alias cairo_text_extents_t TextExtents; ///ditto 146 public alias cairo_glyph_t Glyph; ///ditto 147 public alias cairo_text_cluster_t TextCluster; ///ditto 148 public alias cairo_text_cluster_flags_t TextClusterFlags; ///ditto 149 public alias cairo_font_slant_t FontSlant; ///ditto 150 public alias cairo_font_weight_t FontWeight; ///ditto 151 public alias cairo_device_type_t DeviceType; ///ditto 152 public alias cairo_font_type_t FontType; ///ditto 153 public alias cairo_region_overlap_t RegionOverlap; ///ditto 154 155 /** 156 * A simple struct to store the coordinates of a point as 157 * doubles or integers. 158 */ 159 public struct Point(T) if(isOneOf!(T, int, double)) 160 { 161 /// 162 public this(T x, T y) 163 { 164 this.x = x; 165 this.y = y; 166 } 167 168 /// 169 T x; 170 /// 171 T y; 172 } 173 174 /// 175 unittest 176 { 177 auto p = Point!double(10, 10); //Type Point!double 178 auto p2 = point(10.0, 10.0); //Type Point!double 179 auto p3 = Point!int(10, 10); //Type Point!int 180 auto p4 = point(10, 10); //Type Point!int 181 assert(p == p2); 182 assert(p3 == p4); 183 } 184 185 /** 186 * Convenience function to create a $(D Point!int) or $(D Point!double). 187 */ 188 auto point(T)(T x, T y) if(is(T == int) || is(T == double)) 189 { 190 return Point!T(x,y); 191 } 192 193 /** 194 * A simple struct representing a rectangle with $(D int) or $(D double) values 195 */ 196 public struct Rectangle(T) if(isOneOf!(T, int, double)) 197 { 198 /// 199 public this(Point!T point, T width, T height) 200 { 201 this.point = point; 202 this.width = width; 203 this.height = height; 204 } 205 206 ///ditto 207 public this(T x, T y, T width, T height) 208 { 209 this.point.x = x; 210 this.point.y = y; 211 this.width = width; 212 this.height = height; 213 } 214 215 ///TOP-LEFT point of the rectangle 216 Point!T point; 217 /// 218 T width; 219 /// 220 T height; 221 } 222 223 /** 224 * Convenience function to create a $(D Rectangle!int) or $(D Rectangle!double). 225 */ 226 auto rectangle(T)(T x, T y, T width, T height) if(isOneOf!(T, int, double)) 227 { 228 return Rectangle!(T)(x, y, width, height); 229 } 230 231 ///ditto 232 auto rectangle(T)(Point!T point, T width, T height) if(isOneOf!(T, int, double)) 233 { 234 return Rectangle!(T)(point, width, height); 235 } 236 237 /// 238 unittest 239 { 240 auto a = rectangle(1, 1, 4, 4); 241 Rectangle!int rectInt = a; 242 auto b = rectangle(0.99, 0.99, 3.99, 3.99); 243 Rectangle!double rectDouble = b; 244 } 245 246 /** 247 * A simple struct representing a size with only $(D int) or $(D double) values 248 */ 249 public struct Size(T) if(is(T == int) || is(T == double)) 250 { 251 /// 252 public this(T width, T height) 253 { 254 this.width = width; 255 this.height = height; 256 } 257 258 /// 259 T width, height; 260 } 261 262 /// 263 unittest 264 { 265 auto a = Size!int(10, 10); 266 auto a2 = size(10, 10); 267 auto b = Size!double(5, 5); 268 auto b2 = size(5.0, 5.0); 269 assert(a == a2); 270 assert(b == b2); 271 } 272 273 /** 274 * Convenience function to create a $(D Size!int) or $(D Size!double). 275 */ 276 auto size(T)(T width, T height) if(isOneOf!(T, int, double)) 277 { 278 return Size!(T)(width, height); 279 } 280 281 /** 282 * A simple struct representing a box. 283 * Used for Extents. 284 */ 285 public struct Box 286 { 287 /// 288 public this(Point!double point1, Point!double point2) 289 { 290 this.point1 = point1; 291 this.point2 = point2; 292 } 293 /// 294 public this(double x1, double y1, double x2, double y2) 295 { 296 this.point1.x = x1; 297 this.point1.y = y1; 298 this.point2.x = x2; 299 this.point2.y = y2; 300 } 301 ///Top-left point 302 Point!double point1; 303 ///Bottom-right point 304 Point!double point2; 305 } 306 307 /** 308 * A simple struct representing a resolution 309 */ 310 public struct Resolution 311 { 312 /// 313 public this(double resX, double resY) 314 { 315 this.x = resX; 316 this.y = resY; 317 } 318 319 ///In pixels per inch 320 double x, y; 321 } 322 323 /** 324 * Struct representing a RGBA color 325 */ 326 public struct RGBA 327 { 328 /// 329 public this(double red, double green, double blue, double alpha) 330 { 331 this.red = red; 332 this.green = green; 333 this.blue = blue; 334 this.alpha = alpha; 335 } 336 /// 337 public double red, green, blue, alpha; 338 339 ///convert RGBA struct to RGB struct. Alpha is discarded 340 public RGB opCast(RGB)() 341 { 342 return RGB(red, green, blue); 343 } 344 } 345 346 /** 347 * Struct representing a RGB color 348 */ 349 public struct RGB 350 { 351 /// 352 public this(double red, double green, double blue) 353 { 354 this.red = red; 355 this.green = green; 356 this.blue = blue; 357 } 358 /// 359 public double red, green, blue; 360 361 ///convert RGBA struct to RGB struct. Alpha is set to '1.0' 362 public RGBA opCast(RGBA)() 363 { 364 return RGBA(red, green, blue, 1.0); 365 } 366 } 367 368 unittest 369 { 370 auto rgb1 = RGB(0.1, 0.2, 0.3); 371 auto rgba1 = cast(RGBA)rgb1; 372 assert(rgba1.red == rgb1.red); 373 assert(rgba1.green == rgb1.green); 374 assert(rgba1.blue == rgb1.blue); 375 assert(rgba1.alpha == 1.0); 376 377 auto rgba2 = RGBA(0.3, 0.2, 0.1, 0.5); 378 auto rgb2 = cast(RGB)rgba2; 379 assert(rgba2.red == rgb2.red); 380 assert(rgba2.green == rgb2.green); 381 assert(rgba2.blue == rgb2.blue); 382 } 383 384 /* From cairo binding documentation: 385 * You should not present an API for mutating or for creating new cairo_path_t 386 * objects. In the future, these guidelines may be extended to present an API 387 * for creating a cairo_path_t from scratch for use with cairo_append_path() 388 * but the current expectation is that cairo_append_path() will mostly be 389 * used with paths from cairo_copy_path().*/ 390 /** 391 * Reference counted wrapper around $(D cairo_path_t). 392 * This struct can only be obtained from cairoD. It cannot be created 393 * manually. 394 */ 395 public struct Path 396 { 397 private: 398 struct Payload 399 { 400 cairo_path_t* _payload; 401 this(cairo_path_t* h) 402 { 403 _payload = h; 404 } 405 ~this() 406 { 407 if(_payload) 408 { 409 cairo_path_destroy(_payload); 410 _payload = null; 411 } 412 } 413 414 // Should never perform these operations 415 this(this) { assert(false); } 416 void opAssign(Path.Payload rhs) { assert(false); } 417 } 418 alias RefCounted!(Payload, RefCountedAutoInitialize.no) Data; 419 Data _data; 420 421 @property cairo_status_t status() 422 { 423 return nativePointer.status; 424 } 425 426 @property cairo_path_data_t* data() 427 { 428 return nativePointer.data; 429 } 430 431 @property int num_data() 432 { 433 return nativePointer.num_data; 434 } 435 436 public: 437 // @BUG@: Can't pass as range if default ctor is disabled 438 // @disable this(); 439 440 /** 441 * Create a Path from a existing $(D cairo_path_t*). 442 * Path is a reference-counted type. It will call $(D cairo_path_destroy) 443 * when there are no more references to the path. 444 * 445 * This means you should not destroy the $(D cairo_path_t*) manually 446 * and you should not use $(D cairo_path_t*) anymore after you created a Path 447 * with this constructor. 448 * 449 * Warning: 450 * $(RED Only use this if you know what your doing! 451 * This function should not be needed for standard cairoD usage.) 452 */ 453 this(cairo_path_t* path) 454 { 455 throwError(path.status); 456 _data = Data(path); 457 } 458 459 /** 460 * The underlying $(D cairo_path_t*) handle 461 */ 462 @property cairo_path_t* nativePointer() 463 { 464 return _data._payload; 465 } 466 467 version(D_Ddoc) 468 { 469 /** 470 * Enable / disable memory management debugging for this Path 471 * instance. Only available if both cairoD and the cairoD user 472 * code were compiled with "debug=RefCounted" 473 * 474 * Output is written to stdout, see 475 * $(LINK https://github.com/jpf91/cairoD/wiki/Memory-Management#debugging) 476 * for more information 477 */ 478 @property bool debugging(); 479 ///ditto 480 @property void debugging(bool value); 481 } 482 else debug(RefCounted) 483 { 484 @property bool debugging() 485 { 486 return _data.RefCounted.debugging; 487 } 488 489 @property void debugging(bool value) 490 { 491 _data.RefCounted.debugging = value; 492 } 493 } 494 495 /** 496 * Get a $(D PathRange) for this path to iterate the paths 497 * elements. 498 */ 499 PathRange opSlice() 500 { 501 return PathRange(this); 502 } 503 /// 504 unittest 505 { 506 import std.math, std.stdio, std.array; 507 //Let's create a context first and draw some lines 508 auto surf = new ImageSurface(Format.CAIRO_FORMAT_ARGB32, 100, 100); 509 auto ctx = Context(surf); 510 ctx.moveTo(0.0, 0.0); 511 ctx.lineTo(10.0, 10.0); 512 surf.writeToPNG("test2.png"); 513 514 auto path = ctx.copyPath(); 515 foreach(element; path[]) 516 { 517 switch(element.type) 518 { 519 case PathElementType.CAIRO_PATH_MOVE_TO: 520 auto destination = element[0]; 521 writefln("Move to %s:%s", destination.x, destination.y); 522 break; 523 default: 524 } 525 } 526 } 527 528 unittest 529 { 530 import std.math, std.stdio, std.array; 531 //Let's create a context first and draw some lines 532 auto surf = new ImageSurface(Format.CAIRO_FORMAT_ARGB32, 100, 100); 533 auto ctx = Context(surf); 534 ctx.moveTo(0.0, 0.0); 535 ctx.lineTo(10.0, 10.0); 536 ctx.curveTo(5, 5, 7, 6, 0, 0); 537 ctx.lineTo(10.0, 0.0); 538 539 auto path = ctx.copyPath(); 540 auto pathArray = ctx.copyPath()[].array; 541 assert(pathArray[0].type == PathElementType.CAIRO_PATH_MOVE_TO); 542 assert(pathArray[0][0] == Point!double(0, 0)); 543 assert(pathArray[1].type == PathElementType.CAIRO_PATH_LINE_TO); 544 assert(pathArray[1][0] == Point!double(10, 10)); 545 assert(pathArray[2].type == PathElementType.CAIRO_PATH_CURVE_TO); 546 assert(pathArray[2][0] == Point!double(5, 5)); 547 assert(pathArray[2][1] == Point!double(7, 6)); 548 assert(pathArray[2][2] == Point!double(0, 0)); 549 assert(pathArray[3].type == PathElementType.CAIRO_PATH_LINE_TO); 550 assert(pathArray[3][0] == Point!double(10, 0)); 551 } 552 } 553 554 /** 555 * ForwardRange to iterate a cairo path. 556 * This range keeps a reference to its $(D Path) object, 557 * so it can be passed around without thinking about memory management. 558 */ 559 public struct PathRange 560 { 561 private: 562 Path path; 563 int pos = 0; 564 this(Path path, int pos) 565 { 566 this.path = path; 567 this.pos = pos; 568 } 569 570 public: 571 /** 572 * Constructor to get a PathRange for a $(D Path) object. 573 * You should usually use $(D Path)'s opSlice method insted, see 574 * the $(D Path) documentation for an example. 575 */ 576 this(Path path) 577 { 578 this.path = path; 579 } 580 581 ///ForwardRange implementation 582 @property PathRange save() 583 { 584 return PathRange(path, pos); 585 } 586 587 ///ditto 588 @property bool empty() 589 { 590 assert(pos <= path.num_data); 591 return (pos == path.num_data); 592 } 593 594 ///ditto 595 void popFront() 596 { 597 pos += path.data[pos].header.length; 598 assert(pos <= path.num_data); 599 } 600 601 ///ditto 602 @property PathElement front() 603 { 604 return PathElement(this, &path.data[pos]); 605 } 606 } 607 608 unittest 609 { 610 import std.range; 611 static assert(isForwardRange!PathRange); 612 } 613 614 unittest 615 { 616 import std.array, std.range; 617 //Let's create a context first and draw some lines 618 auto surf = new ImageSurface(Format.CAIRO_FORMAT_ARGB32, 100, 100); 619 auto ctx = Context(surf); 620 ctx.moveTo(0.0, 0.0); 621 ctx.lineTo(10.0, 10.0); 622 ctx.curveTo(5, 5, 7, 6, 0, 0); 623 ctx.lineTo(10.0, 0.0); 624 625 auto path = ctx.copyPath(); 626 auto pathRange = path[]; 627 auto pathRange2 = pathRange.save; 628 pathRange.popFront(); 629 auto pathRange3 = pathRange.save; 630 631 auto pathArray1 = pathRange.array; 632 auto pathArray2 = pathRange2.array; 633 auto pathArray3 = pathRange3.array; 634 assert(pathArray2[0].type == PathElementType.CAIRO_PATH_MOVE_TO); 635 assert(pathArray2[0][0] == Point!double(0, 0)); 636 assert(pathArray2[1].type == PathElementType.CAIRO_PATH_LINE_TO); 637 assert(pathArray2[1][0] == Point!double(10, 10)); 638 assert(pathArray2[2].type == PathElementType.CAIRO_PATH_CURVE_TO); 639 assert(pathArray2[2][0] == Point!double(5, 5)); 640 assert(pathArray2[2][1] == Point!double(7, 6)); 641 assert(pathArray2[2][2] == Point!double(0, 0)); 642 assert(pathArray2[3].type == PathElementType.CAIRO_PATH_LINE_TO); 643 assert(pathArray2[3][0] == Point!double(10, 0)); 644 645 assert(pathArray1 == pathArray3); 646 assert(pathArray2.drop(1) == pathArray1); 647 } 648 649 /** 650 * An element of a cairo $(D Path) and the objects iterated by a 651 * $(D PathRange). 652 */ 653 public struct PathElement 654 { 655 private: 656 cairo_path_data_t* data; 657 PathRange range; 658 659 this(PathRange range, cairo_path_data_t* data) 660 { 661 this.data = data; 662 this.range = range; 663 } 664 public: 665 ///The type of this element. 666 @property PathElementType type() const 667 { 668 return data.header.type; 669 } 670 671 /** 672 * Get a point from this element. 673 * Index is zero-based. The number of available points 674 * depends on the elements $(D type): 675 * -------------------- 676 * CAIRO_PATH_MOVE_TO: 1 point 677 * CAIRO_PATH_LINE_TO: 1 point 678 * CAIRO_PATH_CURVE_TO: 3 points 679 * CAIRO_PATH_CLOSE_PATH: 0 points 680 * -------------------- 681 */ 682 Point!double getPoint(int index) const 683 { 684 //length = 1 + number of points, index 0 based 685 if(index > (data.header.length - 2)) 686 { 687 throw new RangeError(__FILE__, __LINE__); 688 } 689 Point!double p; 690 p.x = data[index+1].point.x; 691 p.y = data[index+1].point.y; 692 return p; 693 } 694 695 ///Convenience operator overload. 696 alias getPoint opIndex; 697 698 void toString(scope void delegate(const(char)[]) sink) const 699 { 700 final switch(type) 701 { 702 case PathElementType.CAIRO_PATH_CLOSE_PATH: 703 sink("(CAIRO_PATH_CLOSE_PATH)"); 704 break; 705 case PathElementType.CAIRO_PATH_CURVE_TO: 706 sink("(CAIRO_PATH_CURVE_TO("); 707 formattedWrite(sink, "%s", this[0]); 708 sink(","); 709 formattedWrite(sink, "%s", this[1]); 710 sink(","); 711 formattedWrite(sink, "%s", this[2]); 712 sink("))"); 713 break; 714 case PathElementType.CAIRO_PATH_LINE_TO: 715 sink("(CAIRO_PATH_LINE_TO("); 716 formattedWrite(sink, "%s", this[0]); 717 sink("))"); 718 break; 719 case PathElementType.CAIRO_PATH_MOVE_TO: 720 sink("(CAIRO_PATH_MOVE_TO("); 721 formattedWrite(sink, "%s", this[0]); 722 sink("))"); 723 break; 724 } 725 } 726 } 727 728 /** 729 * Wrapper for cairo's $(D cairo_matrix_t). 730 * A $(D cairo_matrix_t) holds an affine transformation, such as a scale, 731 * rotation, shear, or a combination of those. The transformation of 732 * a point (x, y) is given by: 733 * -------------------------------------- 734 * x_new = xx * x + xy * y + x0; 735 * y_new = yx * x + yy * y + y0; 736 * -------------------------------------- 737 **/ 738 public struct Matrix 739 { 740 public: 741 /** 742 * Cairo's $(D cairo_matrix_t) struct 743 */ 744 cairo_matrix_t nativeMatrix; 745 /** 746 * Alias, so that $(D cairo_matrix_t) members also work 747 * with this $(D Matrix) struct 748 */ 749 alias nativeMatrix this; 750 751 /** 752 * Sets matrix to be the affine transformation given by xx, yx, xy, yy, x0, y0. 753 * The transformation is given by: 754 * ---------------------- 755 * x_new = xx * x + xy * y + x0; 756 * y_new = yx * x + yy * y + y0; 757 * ---------------------- 758 * 759 * Params: 760 * xx = xx component of the affine transformation 761 * yx = yx component of the affine transformation 762 * xy = xy component of the affine transformation 763 * yy = yy component of the affine transformation 764 * x0 = X translation component of the affine transformation 765 * y0 = Y translation component of the affine transformation 766 */ 767 this(double xx, double yx, double xy, double yy, 768 double x0, double y0) 769 { 770 cairo_matrix_init(&this.nativeMatrix, xx, yx, xy, yy, x0, y0); 771 } 772 773 /** 774 * Modifies matrix to be an identity transformation. 775 */ 776 void initIdentity() 777 { 778 cairo_matrix_init_identity(&this.nativeMatrix); 779 } 780 781 /** 782 * Initializes matrix to a transformation that translates by tx 783 * and ty in the X and Y dimensions, respectively. 784 * 785 * Params: 786 * tx = amount to translate in the X direction 787 * ty = amount to translate in the Y direction 788 */ 789 void initTranslate(double tx, double ty) 790 { 791 cairo_matrix_init_translate(&this.nativeMatrix, tx, ty); 792 } 793 794 /** 795 * nitializes matrix to a transformation that scales by sx and sy 796 * in the X and Y dimensions, respectively. 797 * 798 * Params: 799 * sx = scale factor in the X direction 800 * sy = scale factor in the Y direction 801 */ 802 void initScale(double sx, double sy) 803 { 804 cairo_matrix_init_scale(&this.nativeMatrix, sx, sy); 805 } 806 807 ///ditto 808 void initScale(Point!double point) 809 { 810 initScale(point.x, point.y); 811 } 812 813 /** 814 * Initialized matrix to a transformation that rotates by radians. 815 * 816 * Params: 817 * radians = angle of rotation, in radians. The direction of 818 * rotation is defined such that positive angles rotate in 819 * the direction from the positive X axis toward the positive 820 * Y axis. With the default axis orientation of cairo, 821 * positive angles rotate in a clockwise direction 822 */ 823 void initRotate(double radians) 824 { 825 cairo_matrix_init_rotate(&this.nativeMatrix, radians); 826 } 827 828 /** 829 * Applies a translation by tx, ty to the transformation in matrix. 830 * The effect of the new transformation is to first translate the 831 * coordinates by tx and ty, then apply the original transformation 832 * to the coordinates. 833 * 834 * Params: 835 * tx = amount to translate in the X direction 836 * ty = amount to translate in the Y direction 837 */ 838 void translate(double tx, double ty) 839 { 840 cairo_matrix_translate(&this.nativeMatrix, tx, ty); 841 } 842 843 /** 844 * Applies scaling by sx, sy to the transformation in matrix. 845 * The effect of the new transformation is to first scale the 846 * coordinates by sx and sy, then apply the original transformation 847 * to the coordinates. 848 * 849 * Params: 850 * sx = scale factor in the X direction 851 * sy = scale factor in the Y direction 852 */ 853 void scale(double sx, double sy) 854 { 855 cairo_matrix_scale(&this.nativeMatrix, sx, sy); 856 } 857 858 ///ditto 859 void scale(Point!double point) 860 { 861 scale(point.x, point.y); 862 } 863 864 /** 865 * Applies rotation by radians to the transformation in matrix. 866 * The effect of the new transformation is to first rotate the 867 * coordinates by radians, then apply the original transformation 868 * to the coordinates. 869 * 870 * Params: 871 * radians = angle of rotation, in radians. The direction of 872 * rotation is defined such that positive angles rotate in the 873 * direction from the positive X axis toward the positive Y axis. 874 * With the default axis orientation of cairo, positive angles 875 * rotate in a clockwise direction. 876 */ 877 void rotate(double radians) 878 { 879 cairo_matrix_rotate(&this.nativeMatrix, radians); 880 } 881 882 /** 883 * Changes matrix to be the inverse of its original value. 884 * Not all transformation matrices have inverses; if the matrix 885 * collapses points together (it is degenerate), then it has no 886 * inverse and this function will fail. 887 * 888 * Throws: 889 * If matrix has an inverse, modifies matrix to be the inverse matrix. 890 * Otherwise, throws a cairo exception 891 * with CAIRO_STATUS_INVALID_MATRIX type. 892 */ 893 void invert() 894 { 895 throwError(cairo_matrix_invert(&this.nativeMatrix)); 896 } 897 898 /** 899 * Multiplies the affine transformations in a and b together and 900 * returns the result. The effect of the resulting transformation 901 * is to first apply the transformation in a to the coordinates 902 * and then apply the transformation in b to the coordinates. 903 * 904 * It is allowable for result to be identical to either a or b. 905 */ 906 Matrix opBinary(string op)(Matrix rhs) if(op == "*") 907 { 908 Matrix result; 909 cairo_matrix_multiply(&result.nativeMatrix, &this.nativeMatrix, &rhs.nativeMatrix); 910 return result; 911 } 912 913 /** 914 * Transforms the distance vector (dx,dy) by matrix. This is similar 915 * to $(D transformPoint) except that the translation 916 * components of the transformation are ignored. The calculation 917 * of the returned vector is as follows: 918 * ------------------ 919 * dx2 = dx1 * a + dy1 * c; 920 * dy2 = dx1 * b + dy1 * d; 921 * ------------------ 922 */ 923 Point!double transformDistance(Point!double dist) 924 { 925 cairo_matrix_transform_distance(&this.nativeMatrix, &dist.x, &dist.y); 926 return dist; 927 } 928 929 /** 930 * Transforms the point (x, y) by matrix. 931 */ 932 Point!double transformPoint(Point!double point) 933 { 934 cairo_matrix_transform_point(&this.nativeMatrix, &point.x, &point.y); 935 return point; 936 } 937 } 938 939 /** 940 * A $(D Pattern) represents a source when drawing onto a 941 * $(D Surface). There are different subtypes of $(D Pattern), 942 * for different types of sources; for example, 943 * $(D SolidPattern.fromRGB) creates a pattern for a solid 944 * opaque color. 945 * 946 * Other than various $(D Pattern) subclasses, 947 * some of the pattern types can be implicitly created 948 * using various $(D Context.setSource) functions; 949 * for example $(D Context.setSourceRGB). 950 * 951 * The C type of a pattern can be queried with $(D getType()), 952 * although D polymorphism features also work. 953 * 954 * Memory management of $(D Pattern) can be done with the $(D dispose()) 955 * method, see $(LINK https://github.com/jpf91/cairoD/wiki/Memory-Management#3-RC-class) 956 * 957 * Note: 958 * This class uses the $(D CairoCountedClass) mixin, so all it's members 959 * are also available in $(D Pattern) classes, although they do not show 960 * up in the documentation because of a limitation in ddoc. 961 **/ 962 public class Pattern 963 { 964 /// 965 mixin CairoCountedClass!(cairo_pattern_t*, "cairo_pattern_"); 966 967 protected: 968 /** 969 * Method for use in subclasses. 970 * Calls $(D cairo_pattern_status(nativePointer)) and throws 971 * an exception if the status isn't CAIRO_STATUS_SUCCESS 972 */ 973 final void checkError() 974 { 975 throwError(cairo_pattern_status(nativePointer)); 976 } 977 978 public: 979 /** 980 * Create a $(D Pattern) from a existing $(D cairo_pattern_t*). 981 * Pattern is a garbage collected class. It will call $(D cairo_pattern_destroy) 982 * when it gets collected by the GC or when $(D dispose()) is called. 983 * 984 * Warning: 985 * $(D ptr)'s reference count is not increased by this function! 986 * Adjust reference count before calling it if necessary 987 * 988 * $(RED Only use this if you know what your doing! 989 * This function should not be needed for standard cairoD usage.) 990 */ 991 this(cairo_pattern_t* ptr) 992 { 993 this.nativePointer = ptr; 994 if(!ptr) 995 { 996 throw new CairoException(cairo_status_t.CAIRO_STATUS_NULL_POINTER); 997 } 998 checkError(); 999 } 1000 1001 /** 1002 * The createFromNative method for the Pattern classes. 1003 * See $(LINK https://github.com/jpf91/cairoD/wiki/Memory-Management#createFromNative) 1004 * for more information. 1005 * 1006 * Warning: 1007 * $(RED Only use this if you know what your doing! 1008 * This function should not be needed for standard cairoD usage.) 1009 */ 1010 static Pattern createFromNative(cairo_pattern_t* ptr, bool adjRefCount = true) 1011 { 1012 if(!ptr) 1013 { 1014 throw new CairoException(cairo_status_t.CAIRO_STATUS_NULL_POINTER); 1015 } 1016 throwError(cairo_pattern_status(ptr)); 1017 //Adjust reference count 1018 if(adjRefCount) 1019 cairo_pattern_reference(ptr); 1020 switch(cairo_pattern_get_type(ptr)) 1021 { 1022 case cairo_pattern_type_t.CAIRO_PATTERN_TYPE_LINEAR: 1023 return new LinearGradient(ptr); 1024 case cairo_pattern_type_t.CAIRO_PATTERN_TYPE_RADIAL: 1025 return new RadialGradient(ptr); 1026 case cairo_pattern_type_t.CAIRO_PATTERN_TYPE_SOLID: 1027 return new SolidPattern(ptr); 1028 case cairo_pattern_type_t.CAIRO_PATTERN_TYPE_SURFACE: 1029 return new SurfacePattern(ptr); 1030 default: 1031 return new Pattern(ptr); 1032 } 1033 } 1034 1035 /** 1036 * Sets the mode to be used for drawing outside the area of a pattern. 1037 * See $(D Extend) for details on the semantics of each extend strategy. 1038 * The default extend mode is CAIRO_EXTEND_NONE for surface patterns 1039 * and CAIRO_EXTEND_PAD for gradient patterns. 1040 */ 1041 void setExtend(Extend ext) 1042 { 1043 cairo_pattern_set_extend(this.nativePointer, ext); 1044 checkError(); 1045 } 1046 1047 /** 1048 * Gets the current extend mode for a pattern. See $(D Extend) 1049 * for details on the semantics of each extend strategy. 1050 */ 1051 Extend getExtend() 1052 { 1053 scope(exit) 1054 checkError(); 1055 return cairo_pattern_get_extend(this.nativePointer); 1056 } 1057 1058 /** 1059 * Sets the filter to be used for resizing when using this pattern. 1060 * See $(D Filter) for details on each filter. 1061 * 1062 * Note: 1063 * You might want to control filtering even when you do not have 1064 * an explicit cairo_pattern_t object, (for example when using 1065 * $(D context.setSourceSourface())). In these cases, it is convenient 1066 * to use $(D Context.getSource()) to get access to the pattern 1067 * that cairo creates implicitly. 1068 * For example: 1069 * ------------------------ 1070 * context.setSourceSurface(image, x, y); 1071 * context.getSource().setFilter(Filter.CAIRO_FILTER_NEAREST); 1072 * ------------------------ 1073 */ 1074 void setFilter(Filter fil) 1075 { 1076 cairo_pattern_set_filter(this.nativePointer, fil); 1077 checkError(); 1078 } 1079 1080 /** 1081 * Gets the current filter for a pattern. See $(D Filter) for details on each filter. 1082 */ 1083 Filter getFilter() 1084 { 1085 scope(exit) 1086 checkError(); 1087 return cairo_pattern_get_filter(this.nativePointer); 1088 } 1089 1090 ///Convenience property 1091 void filter(Filter fil) 1092 { 1093 setFilter(fil); 1094 } 1095 1096 ///ditto 1097 Filter filter() 1098 { 1099 return getFilter(); 1100 } 1101 1102 /** 1103 * Sets the pattern's transformation matrix to matrix. 1104 * This matrix is a transformation from user space to pattern space. 1105 * 1106 * When a pattern is first created it always has the identity matrix 1107 * for its transformation matrix, which means that pattern space 1108 * is initially identical to user space. 1109 * Important: Please note that the direction of this transformation 1110 * matrix is from user space to pattern space. This means that if 1111 * you imagine the flow from a pattern to user space (and on to 1112 * device space), then coordinates in that flow will be transformed 1113 * by the inverse of the pattern matrix. 1114 * 1115 * For example, if you want to make a pattern appear twice as large 1116 * as it does by default the correct code to use is: 1117 * ------------------- 1118 * Matrix matrix; 1119 * matrix.initScale(0.5, 0.5); 1120 * pattern.setMatrix(matrix); 1121 * ------------------- 1122 * Meanwhile, using values of 2.0 rather than 0.5 in the code above 1123 * would cause the pattern to appear at half of its default size. 1124 * 1125 * Also, please note the discussion of the user-space locking semantics 1126 * of $(D Context.setSource()). 1127 */ 1128 void setMatrix(Matrix mat) 1129 { 1130 cairo_pattern_set_matrix(this.nativePointer, &mat.nativeMatrix); 1131 checkError(); 1132 } 1133 1134 /** 1135 * Returns the pattern's transformation matrix. 1136 */ 1137 Matrix getMatrix() 1138 { 1139 Matrix ma; 1140 cairo_pattern_get_matrix(this.nativePointer, &ma.nativeMatrix); 1141 checkError(); 1142 return ma; 1143 } 1144 1145 ///Convenience property 1146 @property void matrix(Matrix mat) 1147 { 1148 setMatrix(mat); 1149 } 1150 1151 ///ditto 1152 @property Matrix matrix() 1153 { 1154 return getMatrix(); 1155 } 1156 1157 /** 1158 * This function returns the C type of a pattern. See $(D PatternType) 1159 * for available types. 1160 */ 1161 PatternType getType() 1162 { 1163 scope(exit) 1164 checkError(); 1165 return cairo_pattern_get_type(this.nativePointer); 1166 } 1167 1168 ///Convenience property 1169 @property PatternType type() 1170 { 1171 return getType(); 1172 } 1173 1174 //Cairo binding guidelines say we shouldn't wrap these 1175 /* 1176 void setUserData(const cairo_user_data_key_t* key, void* data, cairo_destroy_func_t destroy) 1177 { 1178 cairo_pattern_set_user_data(this.nativePointer, key, data, destroy); 1179 checkError(); 1180 } 1181 1182 void* getUserData(const cairo_user_data_key_t* key) 1183 { 1184 scope(exit) 1185 checkError(); 1186 return cairo_pattern_get_user_data(this.nativePointer, key); 1187 }*/ 1188 } 1189 1190 /** 1191 * A solid pattern. 1192 * 1193 * Use the $(D fromRGB) and $(D fromRGBA) methods to create an 1194 * instance. 1195 */ 1196 public class SolidPattern : Pattern 1197 { 1198 public: 1199 /** 1200 * Create a $(D SolidPattern) from a existing $(D cairo_pattern_t*). 1201 * SolidPattern is a garbage collected class. It will call $(D cairo_pattern_destroy) 1202 * when it gets collected by the GC or when $(D dispose()) is called. 1203 * 1204 * Warning: 1205 * $(D ptr)'s reference count is not increased by this function! 1206 * Adjust reference count before calling it if necessary 1207 * 1208 * $(RED Only use this if you know what your doing! 1209 * This function should not be needed for standard cairoD usage.) 1210 */ 1211 this(cairo_pattern_t* ptr) 1212 { 1213 super(ptr); 1214 } 1215 1216 /** 1217 * Creates a new $(D SolidPattern) corresponding to an opaque color. 1218 * The color components are floating point numbers in the range 0 1219 * to 1. If the values passed in are outside that range, they will 1220 * be clamped. 1221 */ 1222 static SolidPattern fromRGB(double red, double green, double blue) 1223 { 1224 return new SolidPattern(cairo_pattern_create_rgb(red, green, blue)); 1225 } 1226 1227 ///ditto 1228 static SolidPattern fromRGB(RGB rgb) 1229 { 1230 return new SolidPattern(cairo_pattern_create_rgb(rgb.red, rgb.green, rgb.blue)); 1231 } 1232 1233 /** 1234 * Creates a new $(D SolidPattern) corresponding to a translucent color. 1235 * The color components are floating point numbers in the range 0 to 1. 1236 * If the values passed in are outside that range, they will be clamped. 1237 */ 1238 static SolidPattern fromRGBA(double red, double green, double blue, double alpha) 1239 { 1240 return new SolidPattern(cairo_pattern_create_rgba(red, green, blue, alpha)); 1241 } 1242 1243 ///ditto 1244 static SolidPattern fromRGBA(RGBA rgba) 1245 { 1246 return new SolidPattern(cairo_pattern_create_rgba(rgba.red,rgba. green, rgba.blue, rgba.alpha)); 1247 } 1248 1249 /** 1250 * Gets the solid color for a solid color pattern. 1251 */ 1252 RGBA getRGBA() 1253 { 1254 RGBA col; 1255 cairo_pattern_get_rgba(this.nativePointer, &col.red, &col.green, &col.blue, &col.alpha); 1256 checkError(); 1257 return col; 1258 } 1259 1260 ///Convenience property (todo: dubious due to lowercase requirement) 1261 @property RGBA rgba() 1262 { 1263 return getRGBA(); 1264 } 1265 } 1266 1267 /** 1268 * A surface pattern. 1269 * 1270 * Use the $(this(Surface)) constructor to create an 1271 * instance. 1272 */ 1273 public class SurfacePattern : Pattern 1274 { 1275 public: 1276 /** 1277 * Create a $(D SurfacePattern) from a existing $(D cairo_pattern_t*). 1278 * SurfacePattern is a garbage collected class. It will call $(D cairo_pattern_destroy) 1279 * when it gets collected by the GC or when $(D dispose()) is called. 1280 * 1281 * Warning: 1282 * $(D ptr)'s reference count is not increased by this function! 1283 * Adjust reference count before calling it if necessary 1284 * 1285 * $(RED Only use this if you know what your doing! 1286 * This function should not be needed for standard cairoD usage.) 1287 */ 1288 this(cairo_pattern_t* ptr) 1289 { 1290 super(ptr); 1291 } 1292 1293 /** 1294 * Create a new $(D SurfacePattern) for the given surface. 1295 */ 1296 this(Surface surface) 1297 { 1298 super(cairo_pattern_create_for_surface(surface.nativePointer)); 1299 } 1300 1301 /** 1302 * Gets the $(D Surface) of a SurfacePattern. 1303 */ 1304 Surface getSurface() 1305 { 1306 cairo_surface_t* ptr; 1307 throwError(cairo_pattern_get_surface(this.nativePointer, &ptr)); 1308 return Surface.createFromNative(ptr); 1309 } 1310 1311 ///Convenience property 1312 @property Surface surface() 1313 { 1314 return getSurface(); 1315 } 1316 } 1317 1318 /** 1319 * Base class for $(D LinearGradient) and $(D RadialGradient). 1320 * 1321 * It's not possible to create instances of this class. 1322 */ 1323 public class Gradient : Pattern 1324 { 1325 public: 1326 /** 1327 * Create a $(D Gradient) from a existing $(D cairo_pattern_t*). 1328 * Gradient is a garbage collected class. It will call $(D cairo_pattern_destroy) 1329 * when it gets collected by the GC or when $(D dispose()) is called. 1330 * 1331 * Warning: 1332 * $(D ptr)'s reference count is not increased by this function! 1333 * Adjust reference count before calling it if necessary 1334 * 1335 * $(RED Only use this if you know what your doing! 1336 * This function should not be needed for standard cairoD usage.) 1337 */ 1338 this(cairo_pattern_t* ptr) 1339 { 1340 super(ptr); 1341 } 1342 1343 /** 1344 * Adds an opaque color stop to a gradient pattern. The offset 1345 * specifies the location along the gradient's control vector. 1346 * For example, a $(D LinearGradient)'s control vector is from 1347 * (x0,y0) to (x1,y1) while a $(D RadialGradient)'s control vector is 1348 * from any point on the start circle to the corresponding point 1349 * on the end circle. 1350 * 1351 * The color is specified in the same way as in $(D context.setSourceRGB()). 1352 * 1353 * If two (or more) stops are specified with identical offset 1354 * values, they will be sorted according to the order in which the 1355 * stops are added, (stops added earlier will compare less than 1356 * stops added later). This can be useful for reliably making sharp 1357 * color transitions instead of the typical blend. 1358 * 1359 * Params: 1360 * offset = an offset in the range [0.0 .. 1.0] 1361 * 1362 * Note: If the pattern is not a gradient pattern, (eg. a linear 1363 * or radial pattern), then the pattern will be put into an error 1364 * status with a status of CAIRO_STATUS_PATTERN_TYPE_MISMATCH. 1365 */ 1366 void addColorStopRGB(double offset, RGB color) 1367 { 1368 cairo_pattern_add_color_stop_rgb(this.nativePointer, offset, 1369 color.red, color.green, color.blue); 1370 checkError(); 1371 } 1372 1373 ///ditto 1374 void addColorStopRGB(double offset, double red, double green, double blue) 1375 { 1376 cairo_pattern_add_color_stop_rgb(this.nativePointer, offset, 1377 red, green, blue); 1378 checkError(); 1379 } 1380 1381 /** 1382 * Adds a translucent color stop to a gradient pattern. The offset 1383 * specifies the location along the gradient's control vector. For 1384 * example, a linear gradient's control vector is from (x0,y0) to 1385 * (x1,y1) while a radial gradient's control vector is from any point 1386 * on the start circle to the corresponding point on the end circle. 1387 * 1388 * The color is specified in the same way as in 1389 * $(D context.setSourceRGBA()). 1390 * 1391 * If two (or more) stops are specified with identical offset values, 1392 * they will be sorted according to the order in which the stops are added, 1393 * (stops added earlier will compare less than stops added later). 1394 * This can be useful for reliably making sharp color transitions 1395 * instead of the typical blend. 1396 * 1397 * Params: 1398 * offset = an offset in the range [0.0 .. 1.0] 1399 * 1400 * Note: If the pattern is not a gradient pattern, (eg. a linear 1401 * or radial pattern), then the pattern will be put into an error 1402 * status with a status of CAIRO_STATUS_PATTERN_TYPE_MISMATCH. 1403 */ 1404 void addColorStopRGBA(double offset, RGBA color) 1405 { 1406 cairo_pattern_add_color_stop_rgba(this.nativePointer, offset, 1407 color.red, color.green, color.blue, color.alpha); 1408 checkError(); 1409 } 1410 1411 ///ditto 1412 void addColorStopRGBA(double offset, double red, double green, 1413 double blue, double alpha) 1414 { 1415 cairo_pattern_add_color_stop_rgba(this.nativePointer, offset, 1416 red, green, blue, alpha); 1417 checkError(); 1418 } 1419 1420 /** 1421 * Gets the number of color stops specified in the given gradient pattern. 1422 */ 1423 int getColorStopCount() 1424 { 1425 int tmp; 1426 cairo_pattern_get_color_stop_count(this.nativePointer, &tmp); 1427 checkError(); 1428 return tmp; 1429 } 1430 1431 ///Convenience alias 1432 alias getColorStopCount colorStopCount; 1433 1434 /** 1435 * Gets the color and offset information at the given index for a 1436 * gradient pattern. Values of index are 0 to 1 less than the number 1437 * returned by $(D getColorStopCount()). 1438 * 1439 * Params: 1440 * index = index of the stop to return data for 1441 * offset = output: Returns the offset of the color stop 1442 * color = output: Returns the color of the color stop 1443 * 1444 * TODO: Array/Range - like interface? 1445 */ 1446 void getColorStopRGBA(int index, out double offset, out RGBA color) 1447 { 1448 throwError(cairo_pattern_get_color_stop_rgba(this.nativePointer, index, &offset, 1449 &color.red, &color.green, &color.blue, &color.alpha)); 1450 } 1451 } 1452 1453 /** 1454 * A linear gradient. 1455 * 1456 * Use the $(D this(Point!double p1, Point!double p2)) constructor to create an 1457 * instance. 1458 */ 1459 public class LinearGradient : Gradient 1460 { 1461 public: 1462 /** 1463 * Create a $(D LinearGradient) from a existing $(D cairo_pattern_t*). 1464 * LinearGradient is a garbage collected class. It will call $(D cairo_pattern_destroy) 1465 * when it gets collected by the GC or when $(D dispose()) is called. 1466 * 1467 * Warning: 1468 * $(D ptr)'s reference count is not increased by this function! 1469 * Adjust reference count before calling it if necessary 1470 * 1471 * $(RED Only use this if you know what your doing! 1472 * This function should not be needed for standard cairoD usage.) 1473 */ 1474 this(cairo_pattern_t* ptr) 1475 { 1476 super(ptr); 1477 } 1478 1479 /** 1480 * Create a new linear gradient $(D Pattern) along the line defined 1481 * by p1 and p2. Before using the gradient pattern, a number of 1482 * color stops should be defined using $(D Gradient.addColorStopRGB()) 1483 * or $(D Gradient.addColorStopRGBA()). 1484 * 1485 * Params: 1486 * p1 = the start point 1487 * p2 = the end point 1488 * 1489 * Note: The coordinates here are in pattern space. For a new pattern, 1490 * pattern space is identical to user space, but the relationship 1491 * between the spaces can be changed with $(D Pattern.setMatrix()). 1492 */ 1493 this(Point!double p1, Point!double p2) 1494 { 1495 super(cairo_pattern_create_linear(p1.x, p1.y, p2.x, p2.y)); 1496 } 1497 ///ditto 1498 this(double x1, double y1, double x2, double y2) 1499 { 1500 super(cairo_pattern_create_linear(x1, y1, x2, y2)); 1501 } 1502 1503 /** 1504 * Gets the gradient endpoints for a linear gradient. 1505 * 1506 * Returns: 1507 * Point[0] = the first point 1508 * 1509 * Point[1] = the second point 1510 */ 1511 Point!(double)[2] getLinearPoints() 1512 { 1513 Point!(double)[2] tmp; 1514 throwError(cairo_pattern_get_linear_points(this.nativePointer, &tmp[0].x, &tmp[0].y, 1515 &tmp[1].x, &tmp[1].y)); 1516 return tmp; 1517 } 1518 1519 ///Convenience alias 1520 alias getLinearPoints linearPoints; 1521 } 1522 1523 /** 1524 * A radial gradient. 1525 * 1526 * Use the $(D this(Point!double c0, double radius0, Point!double c1, double radius1)) 1527 * constructor to create an instance. 1528 */ 1529 public class RadialGradient : Gradient 1530 { 1531 public: 1532 /** 1533 * Create a $(D RadialGradient) from a existing $(D cairo_pattern_t*). 1534 * RadialGradient is a garbage collected class. It will call $(D cairo_pattern_destroy) 1535 * when it gets collected by the GC or when $(D dispose()) is called. 1536 * 1537 * Warning: 1538 * $(D ptr)'s reference count is not increased by this function! 1539 * Adjust reference count before calling it if necessary 1540 * 1541 * $(RED Only use this if you know what your doing! 1542 * This function should not be needed for standard cairoD usage.) 1543 */ 1544 this(cairo_pattern_t* ptr) 1545 { 1546 super(ptr); 1547 } 1548 1549 /** 1550 * Creates a new radial gradient $(D pattern) between the two 1551 * circles defined by (c0, radius0) and (c1, radius1). Before 1552 * using the gradient pattern, a number of color stops should 1553 * be defined using $(D Pattern.addColorStopRGB()) or 1554 * $(D Pattern.addColorStopRGBA()). 1555 * 1556 * Params: 1557 * c0 = center of the start circle 1558 * radius0 = radius of the start circle 1559 * c1 = center of the end circle 1560 * radius1 = radius of the end circle 1561 * 1562 * Note: The coordinates here are in pattern space. For a new pattern, 1563 * pattern space is identical to user space, but the relationship 1564 * between the spaces can be changed with $(D Pattern.setMatrix()). 1565 */ 1566 this(Point!double c0, double radius0, Point!double c1, double radius1) 1567 { 1568 super(cairo_pattern_create_radial(c0.x, c0.y, radius0, c1.x, c1.y, radius1)); 1569 } 1570 ///ditto 1571 this(double c0x, double c0y, double radius0, double c1x, double c1y, double radius1) 1572 { 1573 super(cairo_pattern_create_radial(c0x, c0y, radius0, c1x, c1y, radius1)); 1574 } 1575 1576 /** 1577 * Gets the gradient endpoint circles for a radial gradient, 1578 * each specified as a center coordinate and a radius. 1579 */ 1580 void getRadialCircles(out Point!double c0, out Point!double c1, out double radius0, out double radius1) 1581 { 1582 throwError(cairo_pattern_get_radial_circles(this.nativePointer, &c0.x, &c0.y, &radius0, 1583 &c1.x, &c1.y, &radius1)); 1584 } 1585 } 1586 1587 /** 1588 * Devices are the abstraction Cairo employs for the rendering system used 1589 * by a $(D Surface). You can get the device of a surface using 1590 * $(D Surface.getDevice()). 1591 * 1592 * Devices are created using custom functions specific to the rendering 1593 * system you want to use. See the documentation for the surface types 1594 * for those functions. 1595 * 1596 * An important function that devices fulfill is sharing access to the 1597 * rendering system between Cairo and your application. If you want to access 1598 * a device directly that you used to draw to with Cairo, you must first 1599 * call $(D Device.flush()) to ensure that Cairo finishes all operations 1600 * on the device and resets it to a clean state. 1601 * 1602 * Cairo also provides the functions $(D Device.acquire()) and 1603 * $(D Device.release()) to synchronize access to the rendering system 1604 * in a multithreaded environment. This is done internally, but can also 1605 * be used by applications. 1606 * 1607 * Note: 1608 * Please refer to the documentation of each backend for additional usage 1609 * requirements, guarantees provided, and interactions with existing surface 1610 * API of the device functions for surfaces of that type. 1611 * 1612 * Examples: 1613 * ------------------------- 1614 * void my_device_modifying_function(Device device) 1615 * { 1616 * // Ensure the device is properly reset 1617 * device.flush(); 1618 * try 1619 * { 1620 * // Try to acquire the device 1621 * device.acquire(); 1622 * } 1623 * catch(CairoException e) 1624 * { 1625 * writeln(""); 1626 * } 1627 * 1628 * // Release the device when done. 1629 * scope(exit) 1630 * device.release(); 1631 * 1632 * // Do the custom operations on the device here. 1633 * // But do not call any Cairo functions that might acquire devices. 1634 * 1635 * } 1636 * ------------------------- 1637 */ 1638 public class Device 1639 { 1640 /// 1641 mixin CairoCountedClass!(cairo_device_t*, "cairo_device_"); 1642 1643 protected: 1644 /** 1645 * Method for use in subclasses. 1646 * Calls $(D cairo_device_status(nativePointer)) and throws 1647 * an exception if the status isn't CAIRO_STATUS_SUCCESS 1648 */ 1649 final void checkError() 1650 { 1651 throwError(cairo_device_status(nativePointer)); 1652 } 1653 1654 public: 1655 /** 1656 * Create a $(D Device) from a existing $(D cairo_device_t*). 1657 * Device is a garbage collected class. It will call $(D cairo_pattern_destroy) 1658 * when it gets collected by the GC or when $(D dispose()) is called. 1659 * 1660 * Warning: 1661 * $(D ptr)'s reference count is not increased by this function! 1662 * Adjust reference count before calling it if necessary 1663 * 1664 * $(RED Only use this if you know what your doing! 1665 * This function should not be needed for standard cairoD usage.) 1666 */ 1667 this(cairo_device_t* ptr) 1668 { 1669 this.nativePointer = ptr; 1670 if(!ptr) 1671 { 1672 throw new CairoException(cairo_status_t.CAIRO_STATUS_NULL_POINTER); 1673 } 1674 checkError(); 1675 } 1676 1677 /** 1678 * This function finishes the device and drops all references to 1679 * external resources. All surfaces, fonts and other objects created 1680 * for this device will be finished, too. Further operations on 1681 * the device will not affect the device but will instead trigger 1682 * a CAIRO_STATUS_DEVICE_FINISHED exception. 1683 * 1684 * When the reference count reaches zero, cairo will call $(D finish()) 1685 * if it hasn't been called already, before freeing the resources 1686 * associated with the device. 1687 * 1688 * This function may acquire devices. 1689 * 1690 * BUGS: How does "All surfaces, fonts and other objects created 1691 * for this device will be finished" interact with the cairoD? 1692 */ 1693 void finish() 1694 { 1695 cairo_device_finish(this.nativePointer); 1696 checkError(); 1697 } 1698 1699 /** 1700 * Finish any pending operations for the device and also restore 1701 * any temporary modifications cairo has made to the device's state. 1702 * This function must be called before switching from using the 1703 * device with Cairo to operating on it directly with native APIs. 1704 * If the device doesn't support direct access, then this function does nothing. 1705 * 1706 * This function may acquire devices. 1707 */ 1708 void flush() 1709 { 1710 cairo_device_flush(this.nativePointer); 1711 checkError(); 1712 } 1713 1714 /** 1715 * This function returns the C type of a Device. See $(D DeviceType) 1716 * for available types. 1717 */ 1718 DeviceType getType() 1719 { 1720 auto tmp = cairo_device_get_type(this.nativePointer); 1721 checkError(); 1722 return tmp; 1723 } 1724 1725 ///Convenience alias 1726 alias getType type; 1727 1728 /** 1729 * Acquires the device for the current thread. This function will 1730 * block until no other thread has acquired the device. 1731 * 1732 * If no Exception is thrown, you successfully 1733 * acquired the device. From now on your thread owns the device 1734 * and no other thread will be able to acquire it until a matching 1735 * call to $(D Device.release()). It is allowed to recursively 1736 * acquire the device multiple times from the same thread. 1737 * 1738 * Note: 1739 * You must never acquire two different devices at the same time 1740 * unless this is explicitly allowed. Otherwise the possibility 1741 * of deadlocks exist. 1742 * 1743 * As various Cairo functions can acquire devices when called, 1744 * these functions may also cause deadlocks when you call them 1745 * with an acquired device. So you must not have a device acquired 1746 * when calling them. These functions are marked in the documentation. 1747 * 1748 * Throws: 1749 * An exception if the device is in an error state and could not 1750 * be acquired. After a successful call to acquire, a matching call 1751 * to $(D Device.release()) is required. 1752 */ 1753 void acquire() 1754 { 1755 cairo_device_acquire(this.nativePointer); 1756 checkError(); 1757 } 1758 1759 /** 1760 * Releases a device previously acquired using $(D Device.acquire()). 1761 * See that function for details. 1762 */ 1763 void release() 1764 { 1765 cairo_device_release(this.nativePointer); 1766 checkError(); 1767 } 1768 } 1769 1770 /** 1771 * Surface is the abstract type representing all different drawing targets 1772 * that cairo can render to. The actual drawings are performed using a cairo context. 1773 * 1774 * A cairo surface is created by using backend-specific classes, 1775 * typically of the form $(D BackendSurface). 1776 * 1777 * Most surface types allow accessing the surface without using Cairo 1778 * functions. If you do this, keep in mind that it is mandatory that 1779 * you call $(D Surface.flush()) before reading from or writing to the 1780 * surface and that you must use $(D Surface.markDirty()) after modifying it. 1781 */ 1782 public class Surface 1783 { 1784 /// 1785 mixin CairoCountedClass!(cairo_surface_t*, "cairo_surface_"); 1786 1787 protected: 1788 /** 1789 * Method for use in subclasses. 1790 * Calls $(D cairo_surface_status(nativePointer)) and throws 1791 * an exception if the status isn't CAIRO_STATUS_SUCCESS 1792 */ 1793 final void checkError() 1794 { 1795 throwError(cairo_surface_status(nativePointer)); 1796 } 1797 1798 public: 1799 /** 1800 * Create a $(D Surface) from a existing $(D cairo_surface_t*). 1801 * Surface is a garbage collected class. It will call $(D cairo_surface_destroy) 1802 * when it gets collected by the GC or when $(D dispose()) is called. 1803 * 1804 * Warning: 1805 * $(D ptr)'s reference count is not increased by this function! 1806 * Adjust reference count before calling it if necessary 1807 * 1808 * $(RED Only use this if you know what your doing! 1809 * This function should not be needed for standard cairoD usage.) 1810 */ 1811 this(cairo_surface_t* ptr) 1812 { 1813 this.nativePointer = ptr; 1814 if(!ptr) 1815 { 1816 throw new CairoException(cairo_status_t.CAIRO_STATUS_NULL_POINTER); 1817 } 1818 checkError(); 1819 } 1820 1821 /** 1822 * The createFromNative method for the Surface classes. 1823 * See $(LINK https://github.com/jpf91/cairoD/wiki/Memory-Management#createFromNative) 1824 * for more information. 1825 * 1826 * Warning: 1827 * $(RED Only use this if you know what your doing! 1828 * This function should not be needed for standard cairoD usage.) 1829 */ 1830 static Surface createFromNative(cairo_surface_t* ptr, bool adjRefCount = true) 1831 { 1832 if(!ptr) 1833 { 1834 throw new CairoException(cairo_status_t.CAIRO_STATUS_NULL_POINTER); 1835 } 1836 throwError(cairo_surface_status(ptr)); 1837 //Adjust reference count 1838 if(adjRefCount) 1839 cairo_surface_reference(ptr); 1840 switch(cairo_surface_get_type(ptr)) 1841 { 1842 case cairo_surface_type_t.CAIRO_SURFACE_TYPE_IMAGE: 1843 return new ImageSurface(ptr); 1844 static if(CAIRO_HAS_PS_SURFACE) 1845 { 1846 import cairo.ps; 1847 case cairo_surface_type_t.CAIRO_SURFACE_TYPE_PS: 1848 return new PSSurface(ptr); 1849 } 1850 static if(CAIRO_HAS_PDF_SURFACE) 1851 { 1852 import cairo.pdf; 1853 case cairo_surface_type_t.CAIRO_SURFACE_TYPE_PDF: 1854 return new PDFSurface(ptr); 1855 } 1856 static if(CAIRO_HAS_SVG_SURFACE) 1857 { 1858 import cairo.svg; 1859 case cairo_surface_type_t.CAIRO_SURFACE_TYPE_SVG: 1860 return new SVGSurface(ptr); 1861 } 1862 static if(CAIRO_HAS_WIN32_SURFACE) 1863 { 1864 import cairo.win32; 1865 case cairo_surface_type_t.CAIRO_SURFACE_TYPE_WIN32: 1866 return new Win32Surface(ptr); 1867 case cairo_surface_type_t.CAIRO_SURFACE_TYPE_WIN32_PRINTING: 1868 return new Win32Surface(ptr); 1869 } 1870 static if(CAIRO_HAS_XCB_SURFACE) 1871 { 1872 import cairo.xcb; 1873 case cairo_surface_type_t.CAIRO_SURFACE_TYPE_XCB: 1874 return new XCBSurface(ptr); 1875 } 1876 static if(CAIRO_HAS_DIRECTFB_SURFACE) 1877 { 1878 import cairo.directfb; 1879 case cairo_surface_type_t.CAIRO_SURFACE_TYPE_DIRECTFB: 1880 return new DirectFBSurface(ptr); 1881 } 1882 static if(CAIRO_HAS_XLIB_SURFACE) 1883 { 1884 import cairo.xlib; 1885 case cairo_surface_type_t.CAIRO_SURFACE_TYPE_XLIB: 1886 return new XlibSurface(ptr); 1887 } 1888 default: 1889 return new Surface(ptr); 1890 } 1891 } 1892 1893 /** 1894 * Create a new surface that is as compatible as possible with 1895 * an existing surface. For example the new surface will have the 1896 * same fallback resolution and font options as other. Generally, 1897 * the new surface will also use the same backend as other, unless 1898 * that is not possible for some reason. The type of the returned 1899 * surface may be examined with $(D Surface.getType()). 1900 * 1901 * Initially the surface contents are all 0 (transparent if 1902 * contents have transparency, black otherwise.) 1903 * 1904 * Params: 1905 * other = an existing surface used to select the backend of the new surface 1906 * content = the content for the new surface 1907 * width = width of the new surface, (in device-space units) 1908 * height = height of the new surface (in device-space units) 1909 */ 1910 static Surface createSimilar(Surface other, Content content, int width, int height) 1911 { 1912 return createFromNative(cairo_surface_create_similar(other.nativePointer, content, width, height), false); 1913 } 1914 1915 /** 1916 * Create a new surface that is a rectangle within the target surface. 1917 * All operations drawn to this surface are then clipped and translated 1918 * onto the target surface. Nothing drawn via this sub-surface 1919 * outside of its bounds is drawn onto the target surface, 1920 * making this a useful method for passing constrained child 1921 * surfaces to library routines that draw directly onto the parent 1922 * surface, i.e. with no further backend allocations, double 1923 * buffering or copies. 1924 * 1925 * Note: 1926 * The semantics of subsurfaces have not been finalized yet unless 1927 * the rectangle is in full device units, is contained within 1928 * the extents of the target surface, and the target or 1929 * subsurface's device transforms are not changed. 1930 * 1931 * Params: 1932 * target = an existing surface for which the sub-surface will point to 1933 * rect = location of the subsurface 1934 */ 1935 static Surface createForRectangle(Surface target, Rectangle!double rect) 1936 { 1937 return createFromNative(cairo_surface_create_for_rectangle(target.nativePointer, 1938 rect.point.x, rect.point.y, rect.width, rect.height), false); 1939 } 1940 1941 /** 1942 * This function finishes the surface and drops all references 1943 * to external resources. For example, for the Xlib backend it 1944 * means that cairo will no longer access the drawable, which 1945 * can be freed. After calling $(D Surface.finish()) the only 1946 * valid operations on a surface are getting and setting user, 1947 * referencing and destroying, and flushing and finishing it. 1948 * 1949 * Further drawing to the surface will not affect the surface 1950 * but will instead trigger a CAIRO_STATUS_SURFACE_FINISHED exception. 1951 * 1952 * When the reference count id decreased to zero, cairo will call 1953 * $(D Surface.finish()) if it hasn't been called already, before 1954 * freeing the resources associated with the surface. 1955 */ 1956 void finish() 1957 { 1958 cairo_surface_finish(this.nativePointer); 1959 checkError(); 1960 } 1961 1962 /** 1963 * Do any pending drawing for the surface and also restore any temporary 1964 * modifications cairo has made to the surface's state. This function 1965 * must be called before switching from drawing on the surface 1966 * with cairo to drawing on it directly with native APIs. If the 1967 * surface doesn't support direct access, then this function does 1968 * nothing. 1969 */ 1970 void flush() 1971 { 1972 cairo_surface_flush(this.nativePointer); 1973 checkError(); 1974 } 1975 1976 /** 1977 * This function returns the device for a surface. See $(D Device). 1978 */ 1979 Device getDevice() 1980 { 1981 auto ptr = cairo_surface_get_device(this.nativePointer); 1982 if(!ptr) 1983 return null; 1984 cairo_device_reference(ptr); 1985 return new Device(ptr); 1986 } 1987 1988 ///Convenience alias 1989 alias getDevice device; 1990 1991 /** 1992 * Retrieves the default font rendering options for the surface. 1993 * This allows display surfaces to report the correct subpixel 1994 * order for rendering on them, print surfaces to disable hinting 1995 * of metrics and so forth. The result can then be used with 1996 * $(new ScaledFont()). 1997 */ 1998 FontOptions getFontOptions() 1999 { 2000 FontOptions fo = FontOptions.create(); 2001 cairo_surface_get_font_options(this.nativePointer, fo._data._payload); 2002 fo.checkError(); 2003 return fo; 2004 } 2005 2006 ///Convenience alias 2007 alias getFontOptions fontOptions; 2008 2009 /** 2010 * This function returns the content type of surface which indicates 2011 * whether the surface contains color and/or alpha information. 2012 * See $(D Content). 2013 */ 2014 Content getContent() 2015 { 2016 scope(exit) 2017 checkError(); 2018 return cairo_surface_get_content(this.nativePointer); 2019 } 2020 2021 ///Convenience alias 2022 alias getContent content; 2023 2024 /** 2025 * Tells cairo that drawing has been done to surface using means 2026 * other than cairo, and that cairo should reread any cached areas. 2027 * Note that you must call $(D Surface.flush()) before doing such drawing. 2028 */ 2029 void markDirty() 2030 { 2031 cairo_surface_mark_dirty(this.nativePointer); 2032 checkError(); 2033 } 2034 2035 /** 2036 * Like $(D Surface.markDirty()), but drawing has been done only 2037 * to the specified rectangle, so that cairo can retain cached 2038 * contents for other parts of the surface. 2039 * 2040 * Any cached clip set on the surface will be reset by this function, 2041 * to make sure that future cairo calls have the clip set that they expect. 2042 */ 2043 void markDirtyRectangle(int x, int y, int width, int height) 2044 { 2045 cairo_surface_mark_dirty_rectangle(this.nativePointer, x, y, width, height); 2046 checkError(); 2047 } 2048 2049 ///ditto 2050 void markDirtyRectangle(Rectangle!int rect) 2051 { 2052 cairo_surface_mark_dirty_rectangle(this.nativePointer, rect.point.x, 2053 rect.point.y, rect.width, rect.height); 2054 checkError(); 2055 } 2056 2057 /** 2058 * Sets an offset that is added to the device coordinates determined 2059 * by the CTM when drawing to surface. One use case for this function 2060 * is when we want to create a $(D Surface) that redirects drawing 2061 * for a portion of an onscreen surface to an offscreen surface 2062 * in a way that is completely invisible to the user of the cairo API. 2063 * Setting a transformation via $(D Context.translate()) isn't sufficient 2064 * to do this, since functions like $(D Context.deviceToUser()) will 2065 * expose the hidden offset. 2066 * 2067 * Note: 2068 * the offset affects drawing to the surface as well as using the 2069 * surface in a source pattern. 2070 * 2071 * Params: 2072 * x_offset = the offset in the X direction, in device units 2073 * y_offset = the offset in the Y direction, in device units 2074 */ 2075 void setDeviceOffset(double x_offset, double y_offset) 2076 { 2077 cairo_surface_set_device_offset(this.nativePointer, x_offset, y_offset); 2078 checkError(); 2079 } 2080 ///ditto 2081 void setDeviceOffset(Point!double offset) 2082 { 2083 cairo_surface_set_device_offset(this.nativePointer, offset.x, offset.y); 2084 checkError(); 2085 } 2086 2087 /** 2088 * This function returns the previous device offset set 2089 * by $(D Surface.setDeviceOffset()). 2090 * 2091 * Returns: 2092 * Offset in device units 2093 */ 2094 Point!double getDeviceOffset() 2095 { 2096 Point!double tmp; 2097 cairo_surface_get_device_offset(this.nativePointer, &tmp.x, &tmp.y); 2098 checkError(); 2099 return tmp; 2100 } 2101 2102 ///Convenience property function 2103 // todo: enable when new D tuples are implemented 2104 /+@property void deviceOffset(double x_offset, double y_offset) 2105 { 2106 setDeviceOffset(x_offset, y_offset); 2107 }+/ 2108 2109 ///ditto 2110 @property void deviceOffset(Point!double offset) 2111 { 2112 setDeviceOffset(offset); 2113 } 2114 2115 ///ditto 2116 @property Point!double deviceOffset() 2117 { 2118 return getDeviceOffset(); 2119 } 2120 2121 /** 2122 * Set the horizontal and vertical resolution for image fallbacks. 2123 * 2124 * When certain operations aren't supported natively by a backend, 2125 * cairo will fallback by rendering operations to an image and 2126 * then overlaying that image onto the output. For backends that 2127 * are natively vector-oriented, this function can be used to set 2128 * the resolution used for these image fallbacks, (larger values 2129 * will result in more detailed images, but also larger file sizes). 2130 * 2131 * Some examples of natively vector-oriented backends are the ps, 2132 * pdf, and svg backends. 2133 * 2134 * For backends that are natively raster-oriented, image fallbacks 2135 * are still possible, but they are always performed at the native 2136 * device resolution. So this function has no effect on those backends. 2137 * 2138 * Note: 2139 * The fallback resolution only takes effect at the time of 2140 * completing a page (with $(D Context.showPage()) or $(D Context.copyPage())) 2141 * so there is currently no way to have more than one fallback 2142 * resolution in effect on a single page. 2143 * 2144 * The default fallback resoultion is 300 pixels per inch in both 2145 * dimensions. 2146 */ 2147 void setFallbackResolution(Resolution res) 2148 { 2149 cairo_surface_set_fallback_resolution(this.nativePointer, res.x, res.y); 2150 checkError(); 2151 } 2152 2153 /** 2154 * This function returns the previous fallback resolution set 2155 * by $(D setFallbackResolution()), or default 2156 * fallback resolution if never set. 2157 */ 2158 Resolution getFallbackResolution() 2159 { 2160 Resolution res; 2161 cairo_surface_get_fallback_resolution(this.nativePointer, &res.x, &res.y); 2162 checkError(); 2163 return res; 2164 } 2165 2166 ///Convenience property function 2167 @property void fallbackResolution(Resolution res) 2168 { 2169 setFallbackResolution(res); 2170 } 2171 2172 ///ditto 2173 @property Resolution fallbackResolution() 2174 { 2175 return getFallbackResolution(); 2176 } 2177 2178 /** 2179 * This function returns the C type of a Surface. See $(D SurfaceType) 2180 * for available types. 2181 */ 2182 SurfaceType getType() 2183 { 2184 auto tmp = cairo_surface_get_type(this.nativePointer); 2185 checkError(); 2186 return tmp; 2187 } 2188 2189 ///convenience alias 2190 alias getType type; 2191 2192 /* 2193 void setUserData(const cairo_user_data_key_t* key, void* data, cairo_destroy_func_t destroy) 2194 { 2195 cairo_surface_set_user_data(this.nativePointer, key, data, destroy); 2196 checkError(); 2197 } 2198 2199 void* getUserData(const cairo_user_data_key_t* key) 2200 { 2201 scope(exit) 2202 checkError(); 2203 return cairo_surface_get_user_data(this.nativePointer, key); 2204 }*/ 2205 2206 /** 2207 * Emits the current page for backends that support multiple pages, 2208 * but doesn't clear it, so that the contents of the current page 2209 * will be retained for the next page. Use $(D Surface.showPage()) 2210 * if you want to get an empty page after the emission. 2211 * 2212 * There is a convenience function for this that can be called on 2213 * a $(D Context), namely $(D Context.copyPage()). 2214 */ 2215 void copyPage() 2216 { 2217 cairo_surface_copy_page(this.nativePointer); 2218 checkError(); 2219 } 2220 2221 /** 2222 * Emits and clears the current page for backends that support 2223 * multiple pages. Use $(D Surface.copyPage()) if you don't 2224 * want to clear the page. 2225 * 2226 * There is a convenience function for this that can be called on 2227 * a $(D Context), namely $(D Context.showPage()). 2228 */ 2229 void showPage() 2230 { 2231 cairo_surface_show_page(this.nativePointer); 2232 checkError(); 2233 } 2234 2235 /** 2236 * Returns whether the surface supports sophisticated $(D showTextGlyphs()) 2237 * operations. That is, whether it actually uses the provided text 2238 * and cluster data to a $(D showTextGlyphs()) call. 2239 * 2240 * Note: 2241 * Even if this function returns false, a $(D showTextGlyphs()) 2242 * operation targeted at surface will still succeed. It just will 2243 * act like a $(D showGlyphs()) operation. Users can use this 2244 * function to avoid computing UTF-8 text and cluster mapping 2245 * if the target surface does not use it. 2246 * 2247 * Returns: 2248 * true if surface supports $(D showTextGlyphs()), false otherwise 2249 */ 2250 bool hasShowTextGlyphs() 2251 { 2252 scope(exit) 2253 checkError(); 2254 return cairo_surface_has_show_text_glyphs(this.nativePointer) ? true : false; 2255 } 2256 2257 /** 2258 * Attach an image in the format mime_type to surface. To remove 2259 * the data from a surface, call this function with same mime 2260 * type and NULL for data. 2261 * 2262 * The attached image (or filename) data can later be used by 2263 * backends which support it (currently: PDF, PS, SVG and Win32 2264 * Printing surfaces) to emit this data instead of making a snapshot 2265 * of the surface. This approach tends to be faster and requires 2266 * less memory and disk space. 2267 * 2268 * The recognized MIME types are the following: CAIRO_MIME_TYPE_JPEG, 2269 * CAIRO_MIME_TYPE_PNG, CAIRO_MIME_TYPE_JP2, CAIRO_MIME_TYPE_URI. 2270 * 2271 * See corresponding backend surface docs for details about which 2272 * MIME types it can handle. 2273 * 2274 * Caution: the associated MIME data will be discarded if you draw 2275 * on the surface afterwards. Use this function with care. 2276 * 2277 * Params: 2278 * mime_type = the MIME type of the image data 2279 * data = the image data to attach to the surface 2280 * length = the length of the image data 2281 * destroy = a cairo_destroy_func_t which will be called when the 2282 * surface is destroyed or when new image data is attached using 2283 * the same mime type. 2284 * closure = the data to be passed to the destroy notifier 2285 * 2286 * Throws: 2287 * OutOfMemoryError if a slot could not be allocated for the user data. 2288 * 2289 * TODO: More D-like API 2290 * 2291 * Note: 2292 * $(RED Only use this if you know what your doing! Make sure you get 2293 * memory management of the passed in data right!) 2294 */ 2295 void setMimeData(string type, ubyte* data, ulong length, cairo_destroy_func_t destroy, void* closure) 2296 { 2297 throwError(cairo_surface_set_mime_data(this.nativePointer, toStringz(type), 2298 data, length, destroy, closure)); 2299 } 2300 2301 /** 2302 * Return mime data previously attached to surface using the 2303 * specified mime type. If no data has been attached with the given 2304 * mime type, data is set null. 2305 * 2306 * Params: 2307 * type = the mime type of the image data 2308 * 2309 * TODO: More D-like API 2310 * 2311 * Note: 2312 * $(RED Only use this if you know what your doing! Make sure you get 2313 * memory management of the data right!) 2314 */ 2315 void getMimeData(string type, out ubyte* data, out ulong length) 2316 { 2317 cairo_surface_get_mime_data(this.nativePointer, toStringz(type), &data, &length); 2318 checkError(); 2319 } 2320 } 2321 2322 /** 2323 * This function provides a stride value that will respect all alignment 2324 * requirements of the accelerated image-rendering code within cairo. 2325 * 2326 * Examples: 2327 * ----------------------------------- 2328 * int stride; 2329 * ubyte[] data; 2330 * Surface surface; 2331 * 2332 * stride = formatStrideForWidth(format, width); 2333 * data = new ubyte[](stride * height); //could also use malloc 2334 * surface = new ImageSurface(data, format, width, height, stride); 2335 * ----------------------------------- 2336 * 2337 * Params: 2338 * format = The desired Format of an image surface to be created 2339 * width = The desired width of an image surface to be created 2340 * 2341 * Returns: 2342 * the appropriate stride to use given the desired format and width, or 2343 * -1 if either the format is invalid or the width too large. 2344 */ 2345 int formatStrideForWidth(Format format, int width) 2346 { 2347 return cairo_format_stride_for_width(format, width); 2348 } 2349 2350 /** 2351 * Image Surfaces — Rendering to memory buffers 2352 * 2353 * Image surfaces provide the ability to render to memory buffers either 2354 * allocated by cairo or by the calling code. The supported image 2355 * formats are those defined in $(D Format). 2356 */ 2357 public class ImageSurface : Surface 2358 { 2359 public: 2360 /** 2361 * Create a $(D ImageSurface) from a existing $(D cairo_surface_t*). 2362 * ImageSurface is a garbage collected class. It will call $(D cairo_surface_destroy) 2363 * when it gets collected by the GC or when $(D dispose()) is called. 2364 * 2365 * Warning: 2366 * $(D ptr)'s reference count is not increased by this function! 2367 * Adjust reference count before calling it if necessary 2368 * 2369 * $(RED Only use this if you know what your doing! 2370 * This function should not be needed for standard cairoD usage.) 2371 */ 2372 this(cairo_surface_t* ptr) 2373 { 2374 super(ptr); 2375 } 2376 2377 /** 2378 * Creates an image surface of the specified format and dimensions. 2379 * Initially the surface contents are all 0. (Specifically, within 2380 * each pixel, each color or alpha channel belonging to format will 2381 * be 0. The contents of bits within a pixel, but not belonging 2382 * to the given format are undefined). 2383 * 2384 * Params: 2385 * format = format of pixels in the surface to create 2386 * width = width of the surface, in pixels 2387 * height = height of the surface, in pixels 2388 */ 2389 this(Format format, int width, int height) 2390 { 2391 super(cairo_image_surface_create(format, width, height)); 2392 } 2393 2394 /** 2395 * Creates an image surface for the provided pixel data. 2396 * $(RED The output buffer must be kept around until the $(D Surface) 2397 * is destroyed or $(D Surface.finish()) is called on the surface.) 2398 * The initial contents of data will be used as the initial image 2399 * contents; you must explicitly clear the buffer, using, for 2400 * example, $(D Context.rectangle()) and $(D Context.fill()) if you 2401 * want it cleared. 2402 * 2403 * Note that the stride may be larger than width*bytes_per_pixel 2404 * to provide proper alignment for each pixel and row. 2405 * This alignment is required to allow high-performance rendering 2406 * within cairo. The correct way to obtain a legal stride value is 2407 * to call $(D formatStrideForWidth) with the desired format and 2408 * maximum image width value, and then use the resulting stride 2409 * value to allocate the data and to create the image surface. 2410 * See $(D formatStrideForWidth) for example code. 2411 * 2412 * Params: 2413 * data = a pointer to a buffer supplied by the application in 2414 * which to write contents. This pointer must be suitably aligned 2415 * for any kind of variable, (for example, a pointer returned by malloc). 2416 * format = the format of pixels in the buffer 2417 * width = the width of the image to be stored in the buffer 2418 * height = the height of the image to be stored in the buffer 2419 * stride = the number of bytes between the start of rows in the 2420 * buffer as allocated. This value should always be computed 2421 * by $(D formatStrideForWidth) before allocating 2422 * the data buffer. 2423 */ 2424 this(ubyte[] data, Format format, int width, int height, int stride) 2425 { 2426 super(cairo_image_surface_create_for_data(data.ptr, format, width, height, stride)); 2427 } 2428 2429 /** 2430 * Get a pointer to the data of the image surface, 2431 * for direct inspection or modification. 2432 * 2433 * Warning: There's no way to get the size of the buffer from 2434 * cairo, so you'll only get a $(D ubyte*). Be careful! 2435 */ 2436 ubyte* getData() 2437 { 2438 scope(exit) 2439 checkError(); 2440 return cairo_image_surface_get_data(this.nativePointer); 2441 } 2442 2443 ///convenience alias 2444 alias getData data; 2445 2446 /** 2447 * Get the format of the surface. 2448 */ 2449 Format getFormat() 2450 { 2451 scope(exit) 2452 checkError(); 2453 return cairo_image_surface_get_format(this.nativePointer); 2454 } 2455 2456 ///convenience alias 2457 alias getFormat format; 2458 2459 /** 2460 * Get the width of the image surface in pixels. 2461 */ 2462 int getWidth() 2463 { 2464 scope(exit) 2465 checkError(); 2466 return cairo_image_surface_get_width(this.nativePointer); 2467 } 2468 2469 ///convenience alias 2470 alias getWidth width; 2471 2472 /** 2473 * Get the height of the image surface in pixels. 2474 */ 2475 int getHeight() 2476 { 2477 scope(exit) 2478 checkError(); 2479 return cairo_image_surface_get_height(this.nativePointer); 2480 } 2481 2482 ///convenience alias 2483 alias getHeight height; 2484 2485 /** 2486 * Get the stride of the image surface in bytes. 2487 */ 2488 int getStride() 2489 { 2490 scope(exit) 2491 checkError(); 2492 return cairo_image_surface_get_stride(this.nativePointer); 2493 } 2494 2495 ///convenience alias 2496 alias getStride stride; 2497 2498 version(D_Ddoc) 2499 { 2500 /** 2501 * Creates a new image surface and initializes the contents to the given PNG file. 2502 * 2503 * Params: 2504 * file = name of PNG file to load 2505 * 2506 * Note: 2507 * Only available if cairo, cairoD and the cairoD user 2508 * code were compiled with "version=CAIRO_HAS_PNG_FUNCTIONS" 2509 */ 2510 static ImageSurface fromPng(string file); 2511 //TODO: fromPNGStream when phobos gets new streaming api 2512 /** 2513 * Writes the contents of surface to a new file filename as a PNG image. 2514 * 2515 * Params: 2516 * file = the name of a file to write to 2517 * 2518 * Note: 2519 * Only available if cairo, cairoD and the cairoD user 2520 * code were compiled with "version=CAIRO_HAS_PNG_FUNCTIONS" 2521 */ 2522 void writeToPNG(string file); 2523 //TODO: toPNGStream when phobos gets new streaming api 2524 } 2525 else static if(CAIRO_HAS_PNG_FUNCTIONS) 2526 { 2527 static ImageSurface fromPng(string file) 2528 { 2529 return new ImageSurface(cairo_image_surface_create_from_png(toStringz(file))); 2530 } 2531 //TODO: fromPNGStream when phobos gets new streaming api 2532 void writeToPNG(string file) 2533 { 2534 throwError(cairo_surface_write_to_png(this.nativePointer, toStringz(file))); 2535 } 2536 //TODO: toPNGStream when phobos gets new streaming api 2537 } 2538 } 2539 2540 /** 2541 * The cairo drawing context 2542 * 2543 * $(D Context) is the main object used when drawing with cairo. To draw 2544 * with cairo, you create a $(D Context), set the target surface, and drawing 2545 * options for the $(D Context), create shapes with functions like $(D Context.moveTo()) 2546 * and $(D Context.lineTo()), and then draw shapes with $(D Context.stroke()) 2547 * or $(D Context.fill()). 2548 * 2549 * $(D Context)'s can be pushed to a stack via $(D Context.save()). 2550 * They may then safely be changed, without loosing the current state. 2551 * Use $(D Context.restore()) to restore to the saved state. 2552 */ 2553 public struct Context 2554 { 2555 /*---------------------------Reference counting stuff---------------------------*/ 2556 protected: 2557 @property uint _count() 2558 { 2559 return cairo_get_reference_count(this.nativePointer); 2560 } 2561 2562 void _reference() 2563 { 2564 cairo_reference(this.nativePointer); 2565 } 2566 2567 void _dereference() 2568 { 2569 cairo_destroy(this.nativePointer); 2570 } 2571 2572 public: 2573 /** 2574 * The underlying $(D cairo_t*) handle 2575 */ 2576 cairo_t* nativePointer; 2577 version(D_Ddoc) 2578 { 2579 /** 2580 * Enable / disable memory management debugging for this Context 2581 * instance. Only available if both cairoD and the cairoD user 2582 * code were compiled with "debug=RefCounted" 2583 * 2584 * Output is written to stdout, see 2585 * $(LINK https://github.com/jpf91/cairoD/wiki/Memory-Management#debugging) 2586 * for more information 2587 */ 2588 bool debugging = false; 2589 } 2590 else debug(RefCounted) 2591 { 2592 bool debugging = false; 2593 } 2594 2595 /** 2596 * Constructor that tracks the reference count appropriately. If $(D 2597 * !refCountedIsInitialized), does nothing. 2598 */ 2599 this(this) 2600 { 2601 if (this.nativePointer is null) 2602 return; 2603 this._reference(); 2604 debug(RefCounted) 2605 if (this.debugging) 2606 { 2607 writeln(typeof(this).stringof, 2608 "@", cast(void*) this.nativePointer, ": bumped refcount to ", 2609 this._count); 2610 } 2611 } 2612 2613 ~this() 2614 { 2615 this.dispose(); 2616 } 2617 2618 /** 2619 * Explicitly drecrease the reference count. 2620 * 2621 * See $(LINK https://github.com/jpf91/cairoD/wiki/Memory-Management#2.1-structs) 2622 * for more information. 2623 */ 2624 void dispose() 2625 { 2626 if (this.nativePointer is null) 2627 return; 2628 assert(this._count > 0); 2629 if (this._count > 1) 2630 { 2631 debug(RefCounted) 2632 if (this.debugging) 2633 { 2634 writeln(typeof(this).stringof, 2635 "@", cast(void*)this.nativePointer, 2636 ": decrement refcount to ", this._count - 1); 2637 } 2638 this._dereference(); 2639 this.nativePointer = null; 2640 return; 2641 } 2642 debug(RefCounted) 2643 if (this.debugging) 2644 { 2645 write(typeof(this).stringof, 2646 "@", cast(void*)this.nativePointer, ": freeing... "); 2647 stdout.flush(); 2648 } 2649 //Done, deallocate is done by cairo 2650 this._dereference(); 2651 this.nativePointer = null; 2652 debug(RefCounted) if (this.debugging) writeln("done!"); 2653 } 2654 /** 2655 * Assignment operator 2656 */ 2657 void opAssign(typeof(this) rhs) 2658 { 2659 //Black magic? 2660 swap(this.nativePointer, rhs.nativePointer); 2661 debug(RefCounted) 2662 this.debugging = rhs.debugging; 2663 } 2664 /*------------------------End of Reference counting stuff-----------------------*/ 2665 2666 2667 protected: 2668 final void checkError() 2669 { 2670 throwError(cairo_status(nativePointer)); 2671 } 2672 2673 2674 public: 2675 /** 2676 * Creates a new $(D Context) with all graphics state parameters set 2677 * to default values and with target as a target surface. The 2678 * target surface should be constructed with a backend-specific 2679 * function such as $(D new ImageSurface()). 2680 * 2681 * This function references target, so you can immediately call 2682 * $(D Surface.dispose()) on it if you don't need to maintain 2683 * a separate reference to it. 2684 */ 2685 this(Surface target) 2686 { 2687 //cairo_create already references the pointer, so _reference 2688 //isn't necessary 2689 nativePointer = cairo_create(target.nativePointer); 2690 throwError(cairo_status(nativePointer)); 2691 } 2692 2693 /** 2694 * Create a $(D Context) from a existing $(D cairo_t*). 2695 * Context is a garbage collected class. It will call $(D cairo_destroy) 2696 * when it gets collected by the GC or when $(D dispose()) is called. 2697 * 2698 * Warning: 2699 * $(D ptr)'s reference count is not increased by this function! 2700 * Adjust reference count before calling it if necessary 2701 * 2702 * $(RED Only use this if you know what your doing! 2703 * This function should not be needed for standard cairoD usage.) 2704 */ 2705 this(cairo_t* ptr) 2706 { 2707 this.nativePointer = ptr; 2708 if(!ptr) 2709 { 2710 throw new CairoException(cairo_status_t.CAIRO_STATUS_NULL_POINTER); 2711 } 2712 checkError(); 2713 } 2714 2715 /** 2716 * Makes a copy of the current state of cr and saves it on an 2717 * internal stack of saved states for cr. When $(D Context.restore()) 2718 * is called, cr will be restored to the saved state. Multiple 2719 * calls to $(D Context.save()) and $(D Context.restore()) can be nested; each 2720 * call to $(D Context.restore()) restores the state from the matching 2721 * paired $(D Context.save()). 2722 * 2723 * It isn't necessary to clear all saved states before a $(D Context) 2724 * is freed. If the reference count of a $(D Context) drops to zero 2725 * , any saved states will be freed along with the $(D Context). 2726 */ 2727 void save() 2728 { 2729 cairo_save(this.nativePointer); 2730 checkError(); 2731 } 2732 2733 /** 2734 * Restores cr to the state saved by a preceding call to 2735 * $(D Context.save()) and removes that state from the stack of 2736 * saved states. 2737 */ 2738 void restore() 2739 { 2740 cairo_restore(this.nativePointer); 2741 checkError(); 2742 } 2743 2744 /** 2745 * Gets the target surface for the cairo context as passed to 2746 * the constructor. 2747 */ 2748 Surface getTarget() 2749 { 2750 return Surface.createFromNative(cairo_get_target(this.nativePointer)); 2751 } 2752 2753 ///convenience alias 2754 alias getTarget target; 2755 2756 /** 2757 * Temporarily redirects drawing to an intermediate surface known 2758 * as a group. The redirection lasts until the group is completed 2759 * by a call to $(D Context.popGroup()) or $(D Context.popGroupToSource()). 2760 * These calls provide the result of any drawing to the group 2761 * as a pattern, (either as an explicit object, or set as the 2762 * source pattern). 2763 * 2764 * This group functionality can be convenient for performing 2765 * intermediate compositing. One common use of a group is to render 2766 * objects as opaque within the group, (so that they occlude each other), 2767 * and then blend the result with translucence onto the destination. 2768 * 2769 * Groups can be nested arbitrarily deep by making balanced calls 2770 * to $(D Context.pushGgroup())/$(D Context.popGroup()). Each call pushes/pops 2771 * the new target group onto/from a stack. 2772 * 2773 * The $(D Context.pushGroup()) function calls $(D Context.save()) so that any 2774 * changes to the graphics state will not be visible outside the 2775 * group, (the $(D Context.popGroup) functions call $(D Context.restore())). 2776 * 2777 * By default the intermediate group will have a content type of 2778 * CAIRO_CONTENT_COLOR_ALPHA. Other content types can be chosen 2779 * for the group by using $(D Context.pushGroup(Content)) instead. 2780 * 2781 * As an example, here is how one might fill and stroke a path with 2782 * translucence, but without any portion of the fill being visible 2783 * under the stroke: 2784 * ------------------------------- 2785 * cr.pushGroup(); 2786 * cr.setSource(fill_pattern); 2787 * cr.fillPreserve(); 2788 * cr.setSource(stroke_pattern); 2789 * cr.stroke(); 2790 * cr.popGroupToSource(); 2791 * cr.paintWithAlpha(alpha); 2792 * ------------------------------- 2793 */ 2794 void pushGroup() 2795 { 2796 cairo_push_group(this.nativePointer); 2797 checkError(); 2798 } 2799 2800 /** 2801 * Temporarily redirects drawing to an intermediate surface known 2802 * as a group. The redirection lasts until the group is completed 2803 * by a call to $(D Context.popGroup()) or $(D Context.popGroupToSource()). 2804 * These calls provide the result of any drawing to the group as 2805 * a pattern, (either as an explicit object, or set as the source 2806 * pattern). 2807 * 2808 * The group will have a content type of content. The ability to 2809 * control this content type is the only distinction between this 2810 * function and $(D Context.pushGroup()) which you should see for a more 2811 * detailed description of group rendering. 2812 */ 2813 void pushGroup(Content cont) 2814 { 2815 cairo_push_group_with_content(this.nativePointer, cont); 2816 checkError(); 2817 } 2818 2819 /** 2820 * Terminates the redirection begun by a call to $(D Context.pushGroup()) 2821 * or $(D Context.pushGroup(Content)) and returns a new pattern 2822 * containing the results of all drawing operations performed to 2823 * the group. 2824 * 2825 * The $(D Context.popGroup()) function calls $(D Context.restore()), (balancing 2826 * a call to $(D Context.save()) by the $(D Context.pushGroup()) function), so that any 2827 * changes to the graphics state will not be visible outside the group. 2828 */ 2829 Pattern popGroup() 2830 { 2831 auto ptr = cairo_pop_group(this.nativePointer); 2832 return Pattern.createFromNative(ptr, false); 2833 } 2834 2835 /** 2836 * Terminates the redirection begun by a call to $(D Context.pushGroup()) 2837 * or $(D Context.pushGroup(Content)) and installs the resulting 2838 * pattern as the source pattern in the given cairo context. 2839 * 2840 * The behavior of this function is equivalent to the sequence 2841 * of operations: 2842 * ----------------------- 2843 * Pattern group = cr.popGroup(); 2844 * cr.setSource(group); 2845 * group.dispose(); 2846 * ----------------------- 2847 * but is more convenient as their is no need for a variable to 2848 * store the short-lived pointer to the pattern. 2849 * 2850 * The $(D Context.popGroup()) function calls $(D Context.restore()), 2851 * (balancing a call to $(D Context.save()) by the $(D Context.pushGroup()) function), 2852 * so that any changes to the graphics state will not be 2853 * visible outside the group. 2854 */ 2855 void popGroupToSource() 2856 { 2857 cairo_pop_group_to_source(this.nativePointer); 2858 checkError(); 2859 } 2860 2861 /** 2862 * Gets the current destination surface for the context. 2863 * This is either the original target surface as passed to 2864 * the Context constructor or the target surface for the current 2865 * group as started by the most recent call to 2866 * $(D Context.pushGroup()) or $(D Context.pushGroup(Content)). 2867 */ 2868 Surface getGroupTarget() 2869 { 2870 return Surface.createFromNative(cairo_get_group_target(this.nativePointer)); 2871 } 2872 2873 ///convenience alias 2874 alias getGroupTarget groupTarget; 2875 2876 /** 2877 * Sets the source pattern within cr to an opaque color. 2878 * This opaque color will then be used for any subsequent 2879 * drawing operation until a new source pattern is set. 2880 * 2881 * The color components are floating point numbers in the range 2882 * 0 to 1. If the values passed in are outside that range, 2883 * they will be clamped. 2884 * 2885 * The default source pattern is opaque black, 2886 * (that is, it is equivalent to setSourceRGB(0.0, 0.0, 0.0)). 2887 */ 2888 void setSourceRGB(double red, double green, double blue) 2889 { 2890 cairo_set_source_rgb(this.nativePointer, red, green, blue); 2891 checkError(); 2892 } 2893 2894 ///ditto 2895 void setSourceRGB(RGB rgb) 2896 { 2897 cairo_set_source_rgb(this.nativePointer, rgb.red, rgb.green, rgb.blue); 2898 checkError(); 2899 } 2900 2901 /** 2902 * Sets the source pattern within cr to a translucent color. 2903 * This color will then be used for any subsequent drawing 2904 * operation until a new source pattern is set. 2905 * 2906 * The color and alpha components are floating point numbers in 2907 * the range 0 to 1. If the values passed in are outside that 2908 * range, they will be clamped. 2909 * 2910 * The default source pattern is opaque black, (that is, it is 2911 * equivalent to setSourceRGBA(0.0, 0.0, 0.0, 1.0)). 2912 */ 2913 void setSourceRGBA(double red, double green, double blue, double alpha) 2914 { 2915 cairo_set_source_rgba(this.nativePointer, red, green, blue, alpha); 2916 checkError(); 2917 } 2918 2919 ///ditto 2920 void setSourceRGBA(RGBA rgba) 2921 { 2922 cairo_set_source_rgba(this.nativePointer, rgba.red, rgba.green, rgba.blue, rgba.alpha); 2923 checkError(); 2924 } 2925 2926 /** 2927 * Sets the source pattern within cr to source. This pattern will 2928 * then be used for any subsequent drawing operation until 2929 * a new source pattern is set. 2930 * 2931 * Note: The pattern's transformation matrix will be locked to 2932 * the user space in effect at the time of setSource(). This 2933 * means that further modifications of the current transformation 2934 * matrix will not affect the source pattern. 2935 * See $(D Pattern.setMatrix()). 2936 * 2937 * The default source pattern is a solid pattern that is opaque 2938 * black, (that is, it is equivalent 2939 * to setSourceRGB(0.0, 0.0, 0.0)). 2940 */ 2941 void setSource(Pattern pat) 2942 { 2943 cairo_set_source(this.nativePointer, pat.nativePointer); 2944 checkError(); 2945 } 2946 2947 /** 2948 * Gets the current source pattern for cr. 2949 */ 2950 Pattern getSource() 2951 { 2952 return Pattern.createFromNative(cairo_get_source(this.nativePointer)); 2953 } 2954 2955 ///Convenience property 2956 @property void source(Pattern pat) 2957 { 2958 setSource(pat); 2959 } 2960 2961 ///ditto 2962 @property Pattern source() 2963 { 2964 return getSource(); 2965 } 2966 2967 /** 2968 * This is a convenience function for creating a pattern from 2969 * surface and setting it as the source in cr with $(D Context.setSource()). 2970 * 2971 * The x and y parameters give the user-space coordinate at 2972 * which the surface origin should appear. (The surface origin 2973 * is its upper-left corner before any transformation has been 2974 * applied.) The x and y parameters are negated and then set 2975 * as translation values in the pattern matrix. 2976 * 2977 * Other than the initial translation pattern matrix, 2978 * as described above, all other pattern attributes, 2979 * (such as its extend mode), are set to the default values as 2980 * in $(D new SurfacePattern()). The resulting pattern can be 2981 * queried with $(D Context.getSource()) so that these 2982 * attributes can be modified if desired, (eg. to create a 2983 * repeating pattern with $(D Pattern.setExtend())). 2984 * 2985 * Params: 2986 * x = User-space X coordinate for surface origin 2987 * y = User-space Y coordinate for surface origin 2988 */ 2989 void setSourceSurface(Surface sur, double x, double y) 2990 { 2991 cairo_set_source_surface(this.nativePointer, sur.nativePointer, x, y); 2992 checkError(); 2993 } 2994 ///ditto 2995 void setSourceSurface(Surface sur, Point!double p1) 2996 { 2997 cairo_set_source_surface(this.nativePointer, sur.nativePointer, p1.x, p1.y); 2998 checkError(); 2999 } 3000 3001 /** 3002 * Set the antialiasing mode of the rasterizer used for 3003 * drawing shapes. This value is a hint, and a particular 3004 * backend may or may not support a particular value. At 3005 * the current time, no backend supports CAIRO_ANTIALIAS_SUBPIXEL 3006 * when drawing shapes. 3007 * 3008 * Note that this option does not affect text rendering, 3009 * instead see $(D FontOptions.setAntialias()). 3010 */ 3011 void setAntiAlias(AntiAlias antialias) 3012 { 3013 cairo_set_antialias(this.nativePointer, antialias); 3014 checkError(); 3015 } 3016 3017 /** 3018 * Gets the current shape antialiasing mode, as set by $(D setAntiAlias). 3019 */ 3020 AntiAlias getAntiAlias() 3021 { 3022 scope(exit) 3023 checkError(); 3024 return cairo_get_antialias(this.nativePointer); 3025 } 3026 3027 ///Convenience property 3028 @property void antiAlias(AntiAlias aa) 3029 { 3030 setAntiAlias(aa); 3031 } 3032 3033 ///ditto 3034 @property AntiAlias antiAlias() 3035 { 3036 return getAntiAlias(); 3037 } 3038 3039 /** 3040 * Sets the dash pattern to be used by $(D stroke()). A dash 3041 * pattern is specified by dashes, an array of positive values. 3042 * Each value provides the length of alternate "on" and 3043 * "off" portions of the stroke. The offset specifies an offset 3044 * into the pattern at which the stroke begins. 3045 * 3046 * Each "on" segment will have caps applied as if the segment 3047 * were a separate sub-path. In particular, it is valid to use 3048 * an "on" length of 0.0 with CAIRO_LINE_CAP_ROUND or 3049 * CAIRO_LINE_CAP_SQUARE in order to distributed dots 3050 * or squares along a path. 3051 * 3052 * Note: The length values are in user-space units as 3053 * evaluated at the time of stroking. This is not necessarily 3054 * the same as the user space at the time of $(D setDash()). 3055 * 3056 * If dashes is empty dashing is disabled. 3057 * 3058 * If dashes.length is 1 a symmetric pattern is assumed with alternating 3059 * on and off portions of the size specified by the single value 3060 * in dashes. 3061 * 3062 * If any value in dashes is negative, or if all values are 0, then 3063 * cr will be put into an error state with a 3064 * status of CAIRO_STATUS_INVALID_DASH. 3065 * 3066 * Params: 3067 * dashes = an array specifying alternate lengths of on and off stroke portions 3068 * offset = an offset into the dash pattern at which the stroke should start 3069 */ 3070 void setDash(const(double[]) dashes, double offset) 3071 { 3072 cairo_set_dash(this.nativePointer, dashes.ptr, dashes.length.toCairoCount(), offset); 3073 checkError(); 3074 } 3075 3076 /** 3077 * Gets the current dash array. 3078 */ 3079 double[] getDash(out double offset) 3080 { 3081 double[] dashes = new double[](this.getDashCount()); 3082 cairo_get_dash(this.nativePointer, dashes.ptr, &offset); 3083 checkError(); 3084 return dashes; 3085 } 3086 3087 /** 3088 * This function returns the length of the dash array in cr 3089 * (0 if dashing is not currently in effect). 3090 */ 3091 int getDashCount() 3092 { 3093 scope(exit) 3094 checkError(); 3095 return cairo_get_dash_count(this.nativePointer); 3096 } 3097 3098 /** 3099 * Set the current fill rule within the cairo context. The fill 3100 * rule is used to determine which regions are inside or outside 3101 * a complex (potentially self-intersecting) path. The current 3102 * fill rule affects both $(D fill()) and $(D clip()). See 3103 * $(D FillRule) for details on the semantics of each 3104 * available fill rule. 3105 * 3106 * The default fill rule is CAIRO_FILL_RULE_WINDING. 3107 */ 3108 void setFillRule(FillRule rule) 3109 { 3110 cairo_set_fill_rule(this.nativePointer, rule); 3111 checkError(); 3112 } 3113 3114 /** 3115 * Gets the current fill rule, as set by $(D setFillRule). 3116 */ 3117 FillRule getFillRule() 3118 { 3119 scope(exit) 3120 checkError(); 3121 return cairo_get_fill_rule(this.nativePointer); 3122 } 3123 3124 ///Convenience property 3125 @property void fillRule(FillRule rule) 3126 { 3127 setFillRule(rule); 3128 } 3129 3130 ///ditto 3131 @property FillRule fillRule() 3132 { 3133 return getFillRule(); 3134 } 3135 3136 /** 3137 * Sets the current line cap style within the cairo context. 3138 * See $(D LineCap) for details about how the available 3139 * line cap styles are drawn. 3140 * 3141 * As with the other stroke parameters, the current line cap 3142 * style is examined by $(D stroke()), $(D strokeExtents()) 3143 * and $(D strokeToPath()), but does not have any 3144 * effect during path construction. 3145 * 3146 * The default line cap style is CAIRO_LINE_CAP_BUTT. 3147 */ 3148 void setLineCap(LineCap cap) 3149 { 3150 cairo_set_line_cap(this.nativePointer, cap); 3151 checkError(); 3152 } 3153 3154 /** 3155 * Gets the current line cap style, as set by $(D setLineCap()). 3156 */ 3157 LineCap getLineCap() 3158 { 3159 scope(exit) 3160 checkError(); 3161 return cairo_get_line_cap(this.nativePointer); 3162 } 3163 3164 ///Convenience property 3165 @property void lineCap(LineCap cap) 3166 { 3167 setLineCap(cap); 3168 } 3169 3170 ///ditto 3171 @property LineCap lineCap() 3172 { 3173 return getLineCap(); 3174 } 3175 3176 /** 3177 * Sets the current line join style within the cairo context. 3178 * See $(D LineJoin) for details about how the available 3179 * line join styles are drawn. 3180 * 3181 * As with the other stroke parametes, the current line join 3182 * style is examined by $(D stroke()), $(D strokeExtents()) 3183 * and $(D strokeToPath()), but does not have any effect 3184 * during path construction. 3185 * 3186 * The default line join style is CAIRO_LINE_JOIN_MITER. 3187 */ 3188 void setLineJoin(LineJoin join) 3189 { 3190 cairo_set_line_join(this.nativePointer, join); 3191 checkError(); 3192 } 3193 3194 /** 3195 * Gets the current line join style, as set by $(D setLineJoin) 3196 */ 3197 LineJoin getLineJoin() 3198 { 3199 scope(exit) 3200 checkError(); 3201 return cairo_get_line_join(this.nativePointer); 3202 } 3203 3204 ///Convenience property 3205 @property void lineJoin(LineJoin join) 3206 { 3207 setLineJoin(join); 3208 } 3209 3210 ///ditto 3211 @property LineJoin lineJoin() 3212 { 3213 return getLineJoin(); 3214 } 3215 3216 /** 3217 * Sets the current line width within the cairo context. The line 3218 * width value specifies the diameter of a pen that is circular 3219 * in user space, (though device-space pen may be an ellipse 3220 * in general due to scaling/shear/rotation of the CTM). 3221 * 3222 * Note: When the description above refers to user space and CTM 3223 * it refers to the user space and CTM in effect at the time 3224 * of the stroking operation, not the user space and CTM in 3225 * effect at the time of the call to $(D setLineWidth()). 3226 * The simplest usage makes both of these spaces identical. 3227 * That is, if there is no change to the CTM between a call to 3228 * $(D setLineWidth()) and the stroking operation, then one 3229 * can just pass user-space values to $(D setLineWidth()) and 3230 * ignore this note. 3231 * 3232 * As with the other stroke parameters, the current line width is 3233 * examined by $(D stroke()), $(D strokeExtents()) 3234 * and $(D strokeToPath()), but does not have any effect during 3235 * path construction. 3236 * 3237 * The default line width value is 2.0. 3238 */ 3239 void setLineWidth(double width) 3240 { 3241 cairo_set_line_width(this.nativePointer, width); 3242 checkError(); 3243 } 3244 3245 /** 3246 * This function returns the current line width value exactly 3247 * as set by cairo_set_line_width(). Note that the value is 3248 * unchanged even if the CTM has changed between the calls 3249 * to $(D setLineWidth()) and $(D getLineWidth()). 3250 */ 3251 double getLineWidth() 3252 { 3253 scope(exit) 3254 checkError(); 3255 return cairo_get_line_width(this.nativePointer); 3256 } 3257 3258 ///Convenience property 3259 @property void lineWidth(double width) 3260 { 3261 setLineWidth(width); 3262 } 3263 3264 ///ditto 3265 @property double lineWidth() 3266 { 3267 return getLineWidth(); 3268 } 3269 3270 /** 3271 * Sets the current miter limit within the cairo context. 3272 * 3273 * If the current line join style is set to 3274 * CAIRO_LINE_JOIN_MITER (see cairo_set_line_join()), the miter 3275 * limit is used to determine whether the lines should be joined 3276 * with a bevel instead of a miter. Cairo divides the length of 3277 * the miter by the line width. If the result is greater than the 3278 * miter limit, the style is converted to a bevel. 3279 * 3280 * As with the other stroke parameters, the current line miter 3281 * limit is examined by $(D stroke()), $(D strokeExtents()) 3282 * and $(D strokeToPath()), but does not have any effect 3283 * during path construction. 3284 * 3285 * The default miter limit value is 10.0, which will convert 3286 * joins with interior angles less than 11 degrees to bevels 3287 * instead of miters. For reference, a miter limit of 2.0 makes 3288 * the miter cutoff at 60 degrees, and a miter limit of 1.414 3289 * makes the cutoff at 90 degrees. 3290 * 3291 * A miter limit for a desired angle can be computed as: miter 3292 * limit = 1/sin(angle/2) 3293 */ 3294 void setMiterLimit(double limit) 3295 { 3296 cairo_set_miter_limit(this.nativePointer, limit); 3297 checkError(); 3298 } 3299 3300 /** 3301 * Gets the current miter limit, as set by $(D setMiterLimit) 3302 */ 3303 double getMiterLimit() 3304 { 3305 scope(exit) 3306 checkError(); 3307 return cairo_get_miter_limit(this.nativePointer); 3308 } 3309 3310 ///Convenience property 3311 @property void miterLimit(double limit) 3312 { 3313 setMiterLimit(limit); 3314 } 3315 3316 ///ditto 3317 @property double miterLimit() 3318 { 3319 return getMiterLimit(); 3320 } 3321 3322 /** 3323 * Sets the compositing operator to be used for all 3324 * drawing operations. See $(D Operator) for details on 3325 * the semantics of each available compositing operator. 3326 * 3327 * The default operator is CAIRO_OPERATOR_OVER. 3328 */ 3329 void setOperator(Operator op) 3330 { 3331 cairo_set_operator(this.nativePointer, op); 3332 checkError(); 3333 } 3334 3335 /** 3336 * Gets the current compositing operator for a cairo context. 3337 */ 3338 Operator getOperator() 3339 { 3340 scope(exit) 3341 checkError(); 3342 return cairo_get_operator(this.nativePointer); 3343 } 3344 3345 ///Convenience property 3346 @property void operator(Operator op) 3347 { 3348 setOperator(op); 3349 } 3350 3351 ///ditto 3352 @property Operator operator() 3353 { 3354 return getOperator(); 3355 } 3356 3357 /** 3358 * Sets the tolerance used when converting paths into trapezoids. 3359 * Curved segments of the path will be subdivided until the maximum 3360 * deviation between the original path and the polygonal 3361 * approximation is less than tolerance. The default value 3362 * is 0.1. A larger value will give better performance, a smaller 3363 * value, better appearance. (Reducing the value from the 3364 * default value of 0.1 is unlikely to improve appearance 3365 * significantly.) The accuracy of paths within Cairo is limited 3366 * by the precision of its internal arithmetic, and the prescribed 3367 * tolerance is restricted to the smallest representable 3368 * internal value. 3369 */ 3370 void setTolerance(double tolerance) 3371 { 3372 cairo_set_tolerance(this.nativePointer, tolerance); 3373 checkError(); 3374 } 3375 3376 /** 3377 * Gets the current tolerance value, as set by $(D setTolerance) 3378 */ 3379 double getTolerance() 3380 { 3381 scope(exit) 3382 checkError(); 3383 return cairo_get_tolerance(this.nativePointer); 3384 } 3385 3386 ///Convenience property 3387 @property void tolerance(double tolerance) 3388 { 3389 setTolerance(tolerance); 3390 } 3391 3392 ///ditto 3393 @property double tolerance() 3394 { 3395 return getTolerance(); 3396 } 3397 3398 /** 3399 * Establishes a new clip region by intersecting the current 3400 * clip region with the current path as it would be filled by 3401 * $(D fill()) and according to the current 3402 * fill rule (see $(D setFillRule())). 3403 * 3404 * After $(D clip()), the current path will be cleared from the 3405 * cairo context. 3406 * 3407 * The current clip region affects all drawing operations by 3408 * effectively masking out any changes to the surface that are 3409 * outside the current clip region. 3410 * 3411 * Calling $(D clip()) can only make the clip region smaller, 3412 * never larger. But the current clip is part of the graphics state, 3413 * so a temporary restriction of the clip region can be achieved 3414 * by calling $(D clip()) within a $(D save())/$(D restore()) 3415 * pair. The only other means of increasing the size of the clip 3416 * region is $(D resetClip()). 3417 */ 3418 void clip() 3419 { 3420 cairo_clip(this.nativePointer); 3421 checkError(); 3422 } 3423 3424 /** 3425 * Establishes a new clip region by intersecting the current clip 3426 * region with the current path as it would be filled by 3427 * $(D fill()) and according to the current fill rule 3428 * (see $(D setFillRule())). 3429 * 3430 * Unlike $(D clip()), $(D clipPreserve()) preserves the 3431 * path within the cairo context. 3432 * 3433 * The current clip region affects all drawing operations by 3434 * effectively masking out any changes to the surface that are 3435 * outside the current clip region. 3436 * 3437 * Calling $(D clipPreserve()) can only make the clip region 3438 * smaller, never larger. But the current clip is part of the 3439 * graphics state, so a temporary restriction of the clip region 3440 * can be achieved by calling $(D clip()) within a $(D save())/$(D restore()) 3441 * pair. The only other means of increasing the size of the clip 3442 * region is $(D resetClip()). 3443 */ 3444 void clipPreserve() 3445 { 3446 cairo_clip_preserve(this.nativePointer); 3447 checkError(); 3448 } 3449 3450 /** 3451 * Computes a bounding box in user coordinates covering the area 3452 * inside the current clip. 3453 */ 3454 Box clipExtents() 3455 { 3456 Box tmp; 3457 cairo_clip_extents(this.nativePointer, &tmp.point1.x, &tmp.point1.y, &tmp.point2.x, &tmp.point2.y); 3458 checkError(); 3459 return tmp; 3460 } 3461 3462 /** 3463 * Tests whether the given point is inside the area that would 3464 * be visible through the current clip, i.e. the area that 3465 * would be filled by a cairo_paint() operation. 3466 * 3467 * See $(D clip()), and $(D clipPreserve()). 3468 */ 3469 bool inClip(Point!double point) 3470 { 3471 scope(exit) 3472 checkError(); 3473 return cairo_in_clip(this.nativePointer, point.x, point.y) ? true : false; 3474 } 3475 3476 /** 3477 * Reset the current clip region to its original, unrestricted 3478 * state. That is, set the clip region to an infinitely 3479 * large shape containing the target surface. Equivalently, 3480 * if infinity is too hard to grasp, one can imagine the clip 3481 * region being reset to the exact bounds of the target surface. 3482 * 3483 * Note that code meant to be reusable should not call 3484 * $(D resetClip()) as it will cause results unexpected by 3485 * higher-level code which calls $(D clip()). Consider using 3486 * $(D save()) and $(D restore()) around $(D clip()) as a 3487 * more robust means of temporarily restricting the clip region. 3488 */ 3489 void resetClip() 3490 { 3491 cairo_reset_clip(this.nativePointer); 3492 checkError(); 3493 } 3494 3495 /** 3496 * Gets the current clip region as a list of rectangles in user 3497 * coordinates. 3498 */ 3499 Rectangle!(double)[] copyClipRectangles() 3500 { 3501 Rectangle!(double)[] list; 3502 auto nList = cairo_copy_clip_rectangle_list(this.nativePointer); 3503 scope(exit) 3504 cairo_rectangle_list_destroy(nList); 3505 throwError(nList.status); 3506 list.length = nList.num_rectangles; 3507 for(int i = 0; i < list.length; i++) 3508 { 3509 list[i].point.x = nList.rectangles[i].x; 3510 list[i].point.y = nList.rectangles[i].y; 3511 list[i].width = nList.rectangles[i].width; 3512 list[i].height = nList.rectangles[i].height; 3513 } 3514 return list; 3515 } 3516 3517 /** 3518 * A drawing operator that fills the current path according to 3519 * the current fill rule, (each sub-path is implicitly closed 3520 * before being filled). After c$(D fill()), the current 3521 * path will be cleared from the cairo context. See 3522 * $(D setFillRule()) and $(D fillPreserve()). 3523 */ 3524 void fill() 3525 { 3526 cairo_fill(this.nativePointer); 3527 checkError(); 3528 } 3529 3530 /** 3531 * A drawing operator that fills the current path according to 3532 * the current fill rule, (each sub-path is implicitly closed 3533 * before being filled). Unlike $(D fill()), $(D fillPreserve()) 3534 * preserves the path within the cairo context. 3535 */ 3536 void fillPreserve() 3537 { 3538 cairo_fill_preserve(this.nativePointer); 3539 checkError(); 3540 } 3541 3542 /** 3543 * Computes a bounding box in user coordinates covering the area 3544 * that would be affected, (the "inked" area), by a 3545 * $(D fill()) operation given the current path and fill parameters. 3546 * If the current path is empty, returns an empty rectangle 3547 * ((0,0), (0,0)). Surface dimensions and clipping are not 3548 * taken into account. 3549 * 3550 * Contrast with $(D pathExtents()), which is similar, but 3551 * returns non-zero extents for some paths with no inked area, 3552 * (such as a simple line segment). 3553 * 3554 * Note that $(D fillExtents()) must necessarily do more work 3555 * to compute the precise inked areas in light of the fill rule, 3556 * so $(D pathExtents()) may be more desirable for sake of 3557 * performance if the non-inked path extents are desired. 3558 * 3559 * See $(D fill()), $(D setFillRule()) and $(D fillPreserve()). 3560 */ 3561 Box fillExtends() 3562 { 3563 Box tmp; 3564 cairo_fill_extents(this.nativePointer, &tmp.point1.x, &tmp.point1.y, &tmp.point2.x, &tmp.point2.y); 3565 checkError(); 3566 return tmp; 3567 } 3568 3569 /** 3570 * Tests whether the given point is inside the area that would 3571 * be affected by a cairo_fill() operation given the current path 3572 * and filling parameters. Surface dimensions and clipping are not 3573 * taken into account. 3574 * 3575 * See $(D fill()), $(D setFillRule()) and $(D fillPreserve()). 3576 */ 3577 bool inFill(Point!double point) 3578 { 3579 scope(exit) 3580 checkError(); 3581 return cairo_in_fill(this.nativePointer, point.x, point.y) ? true : false; 3582 } 3583 3584 /** 3585 * A drawing operator that paints the current source using the 3586 * alpha channel of pattern as a mask. (Opaque areas of pattern 3587 * are painted with the source, transparent areas are not painted.) 3588 */ 3589 void mask(Pattern pattern) 3590 { 3591 cairo_mask(this.nativePointer, pattern.nativePointer); 3592 checkError(); 3593 } 3594 3595 /** 3596 * A drawing operator that paints the current source using 3597 * the alpha channel of surface as a mask. (Opaque areas of 3598 * surface are painted with the source, transparent areas 3599 * are not painted.) 3600 * 3601 * Params: 3602 * location = coordinates at which to place the origin of surface 3603 */ 3604 void maskSurface(Surface surface, Point!double location) 3605 { 3606 cairo_mask_surface(this.nativePointer, surface.nativePointer, location.x, location.y); 3607 checkError(); 3608 } 3609 ///ditto 3610 void maskSurface(Surface surface, double x, double y) 3611 { 3612 cairo_mask_surface(this.nativePointer, surface.nativePointer, x, y); 3613 checkError(); 3614 } 3615 3616 /** 3617 * A drawing operator that paints the current source everywhere 3618 * within the current clip region. 3619 */ 3620 void paint() 3621 { 3622 cairo_paint(this.nativePointer); 3623 checkError(); 3624 } 3625 3626 /** 3627 * A drawing operator that paints the current source everywhere 3628 * within the current clip region using a mask of constant alpha 3629 * value alpha. The effect is similar to $(D paint()), but 3630 * the drawing is faded out using the alpha value. 3631 */ 3632 void paintWithAlpha(double alpha) 3633 { 3634 cairo_paint_with_alpha(this.nativePointer, alpha); 3635 checkError(); 3636 } 3637 3638 /** 3639 * A drawing operator that strokes the current path according to 3640 * the current line width, line join, line cap, and dash settings. 3641 * After $(D stroke()), the current path will be cleared from 3642 * the cairo context. See $(D setLineWidth()), 3643 * $(D setLineJoin()), $(D setLineCap()), $(D setDash()), 3644 * and $(D strokePreserve()). 3645 * 3646 * Note: Degenerate segments and sub-paths are treated specially 3647 * and provide a useful result. These can result in two 3648 * different situations: 3649 * 3650 * 1. Zero-length "on" segments set in cairo_set_dash(). If the 3651 * cap style is CAIRO_LINE_CAP_ROUND or CAIRO_LINE_CAP_SQUARE 3652 * then these segments will be drawn as circular dots or squares 3653 * respectively. In the case of CAIRO_LINE_CAP_SQUARE, the 3654 * orientation of the squares is determined by the direction 3655 * of the underlying path. 3656 * 3657 * 2. A sub-path created by $(D moveTo()) followed by either a 3658 * $(D closePath()) or one or more calls to $(D lineTo()) to 3659 * the same coordinate as the $(D moveTo()). If the cap style 3660 * is CAIRO_LINE_CAP_ROUND then these sub-paths will be drawn as 3661 * circular dots. Note that in the case of CAIRO_LINE_CAP_SQUARE 3662 * a degenerate sub-path will not be drawn at all, (since the 3663 * correct orientation is indeterminate). 3664 * 3665 * In no case will a cap style of CAIRO_LINE_CAP_BUTT cause 3666 * anything to be drawn in the case of either degenerate 3667 * segments or sub-paths. 3668 */ 3669 void stroke() 3670 { 3671 cairo_stroke(this.nativePointer); 3672 checkError(); 3673 } 3674 3675 /** 3676 * A drawing operator that strokes the current path according to 3677 * the current line width, line join, line cap, and dash settings. 3678 * Unlike $(D stroke()), $(D strokePreserve()) preserves 3679 * the path within the cairo context. 3680 * 3681 * See $(D setLineWidth()), $(D setLineJoin()), 3682 * $(D setLineCap()), $(D set_dash()), and $(D strokePreserve()). 3683 */ 3684 void strokePreserve() 3685 { 3686 cairo_stroke_preserve(this.nativePointer); 3687 checkError(); 3688 } 3689 3690 /** 3691 * Computes a bounding box in user coordinates covering the area 3692 * that would be affected, (the "inked" area), by a $(D stroke()) 3693 * operation given the current path and stroke parameters. If the 3694 * current path is empty, returns an empty rectangle ((0,0), (0,0)). 3695 * Surface dimensions and clipping are not taken into account. 3696 * 3697 * Note that if the line width is set to exactly zero, then 3698 * $(D strokeExtents()) will return an empty rectangle. 3699 * Contrast with $(D pathExtents()) which can be used to 3700 * compute the non-empty bounds as the line width approaches zero. 3701 * 3702 * Note that $(D strokeExtents()) must necessarily do more 3703 * work to compute the precise inked areas in light of the 3704 * stroke parameters, so $(D pathExtents()) may be more 3705 * desirable for sake of performance if non-inked path extents 3706 * are desired. 3707 * 3708 * See $(D stroke()), $(D setLineWidth()), $(D setLineJoin()), 3709 * $(D setLineCap()), $(D set_dash()), and $(D strokePreserve()). 3710 */ 3711 Box strokeExtends() 3712 { 3713 Box tmp; 3714 cairo_stroke_extents(this.nativePointer, &tmp.point1.x, &tmp.point1.y, &tmp.point2.x, &tmp.point2.y); 3715 checkError(); 3716 return tmp; 3717 } 3718 3719 /** 3720 * Tests whether the given point is inside the area that would be 3721 * affected by a cairo_stroke() operation given the current path 3722 * and stroking parameters. Surface dimensions and clipping are 3723 * not taken into account. 3724 * 3725 * See $(D stroke()), $(D setLineWidth()), $(D setLineJoin()), 3726 * $(D setLineCap()), $(D set_dash()), and $(D strokePreserve()). 3727 */ 3728 bool inStroke(Point!double point) 3729 { 3730 scope(exit) 3731 checkError(); 3732 return cairo_in_stroke(this.nativePointer, point.x, point.y) ? true : false; 3733 } 3734 ///ditto 3735 bool inStroke(double x, double y) 3736 { 3737 scope(exit) 3738 checkError(); 3739 return cairo_in_stroke(this.nativePointer, x, y) ? true : false; 3740 } 3741 3742 /** 3743 * Emits the current page for backends that support multiple 3744 * pages, but doesn't clear it, so, the contents of the current 3745 * page will be retained for the next page too. 3746 * Use $(D showPage()) if you want to get an empty page after 3747 * the emission. 3748 * 3749 * This is a convenience function that simply calls $(D Surface.copyPage()) 3750 * on this's target. 3751 */ 3752 void copyPage() 3753 { 3754 cairo_copy_page(this.nativePointer); 3755 checkError(); 3756 } 3757 3758 /** 3759 * Emits and clears the current page for backends that support 3760 * multiple pages. Use $(D copyPage()) if you don't want to 3761 * clear the page. 3762 * 3763 * This is a convenience function that simply calls 3764 * $(D Surface.showPage()) on this's target. 3765 */ 3766 void showPage() 3767 { 3768 cairo_show_page(this.nativePointer); 3769 checkError(); 3770 } 3771 3772 /* 3773 void setUserData(const cairo_user_data_key_t* key, void* data, cairo_destroy_func_t destroy) 3774 { 3775 cairo_set_user_data(this.nativePointer, key, data, destroy); 3776 checkError(); 3777 } 3778 3779 void* getUserData(const cairo_user_data_key_t* key) 3780 { 3781 scope(exit) 3782 checkError(); 3783 return cairo_get_user_data(this.nativePointer, key); 3784 } 3785 */ 3786 3787 /** 3788 * Creates a copy of the current path and returns it to the user 3789 * as a $(D Path). See $(D PathRange) for hints on how to 3790 * iterate over the returned data structure. 3791 */ 3792 Path copyPath() 3793 { 3794 return Path(cairo_copy_path(this.nativePointer)); 3795 } 3796 3797 /** 3798 * Gets a flattened copy of the current path and returns it to 3799 * the user as a $(D Path). See $(D PathRange) for hints 3800 * on how to iterate over the returned data structure. 3801 * 3802 * This function is like $(D copyPath()) except that any 3803 * curves in the path will be approximated with piecewise-linear 3804 * approximations, (accurate to within the current tolerance value). 3805 * That is, the result is guaranteed to not have any elements of 3806 * type CAIRO_PATH_CURVE_TO which will instead be replaced by 3807 * a series of CAIRO_PATH_LINE_TO elements. 3808 */ 3809 Path copyPathFlat() 3810 { 3811 return Path(cairo_copy_path_flat(this.nativePointer)); 3812 } 3813 3814 /** 3815 * Append the path onto the current path. The path may be 3816 * the return value from one of $(D copyPath()) or $(D copyPathFlat()). 3817 */ 3818 void appendPath(Path p) 3819 { 3820 cairo_append_path(this.nativePointer, p.nativePointer); 3821 checkError(); 3822 } 3823 3824 /** 3825 * appendPath for user created paths. There is no high level API 3826 * for user defined paths. Use $(D appendPath(Path p)) for paths 3827 * which were obtained from cairo. 3828 * 3829 * See $(D cairo_path_t) for details 3830 * on how the path data structure should be initialized, 3831 * and note that path.status must be initialized to CAIRO_STATUS_SUCCESS. 3832 * 3833 * Warning: 3834 * $(RED Only use this if you know what your doing! 3835 * This function should not be needed for standard cairoD usage.) 3836 */ 3837 void appendPath(cairo_path_t* path) 3838 { 3839 cairo_append_path(this.nativePointer, path); 3840 checkError(); 3841 } 3842 3843 /** 3844 * Returns whether a current point is defined on the current path. 3845 * See $(D getCurrentPoint()) for details on the current point. 3846 */ 3847 bool hasCurrentPoint() 3848 { 3849 scope(exit) 3850 checkError(); 3851 return cairo_has_current_point(this.nativePointer) ? true : false; 3852 } 3853 3854 /** 3855 * Gets the current point of the current path, which is conceptually 3856 * the final point reached by the path so far. 3857 * 3858 * The current point is returned in the user-space coordinate system. 3859 * If there is no defined current point or if cr is in an error status, 3860 * x and y will both be set to 0.0. It is possible to check 3861 * this in advance with $(D hasCurrentPoint()). 3862 * 3863 * Most path construction functions alter the current point. See 3864 * the following for details on how they affect the current point: 3865 * $(D newPath()), $(D newSubPath()), $(D appendPath()), 3866 * $(D closePath()), $(D moveTo()), $(D lineTo()), 3867 * $(D curveTo()), $(D relMoveTo()), $(D relLineTo()), 3868 * $(D relCurveTo()), $(D arc()), $(D arcNegative()), 3869 * $(D rectangle()), $(D textPath()), $(D glyphPath()), 3870 * $(D strokeToPath()). 3871 * 3872 * Some functions use and alter the current point but do not 3873 * otherwise change current path: $(D showText()). 3874 * 3875 * Some functions unset the current path and as a result, 3876 * current point: $(D fill()), $(D stroke()). 3877 */ 3878 Point!double getCurrentPoint() 3879 { 3880 Point!double tmp; 3881 cairo_get_current_point(this.nativePointer, &tmp.x, &tmp.y); 3882 checkError(); 3883 return tmp; 3884 } 3885 3886 ///convenience alias 3887 alias getCurrentPoint currentPoint; 3888 3889 /** 3890 * Clears the current path. After this call there will be no path 3891 * and no current point. 3892 */ 3893 void newPath() 3894 { 3895 cairo_new_path(this.nativePointer); 3896 checkError(); 3897 } 3898 3899 /** 3900 * Begin a new sub-path. Note that the existing path is not affected. 3901 * After this call there will be no current point. 3902 * 3903 * In many cases, this call is not needed since new sub-paths are 3904 * frequently started with cairo_move_to(). 3905 * 3906 * A call to $(D newSubPath()) is particularly useful when 3907 * beginning a new sub-path with one of the $(D arc()) calls. 3908 * This makes things easier as it is no longer necessary to 3909 * manually compute the arc's initial coordinates for a call 3910 * to $(D moveTo()). 3911 */ 3912 void newSubPath() 3913 { 3914 cairo_new_sub_path(this.nativePointer); 3915 checkError(); 3916 } 3917 3918 /** 3919 * Adds a line segment to the path from the current point to 3920 * the beginning of the current sub-path, (the most recent 3921 * point passed to $(D moveTo())), and closes this sub-path. 3922 * After this call the current point will be at the joined 3923 * endpoint of the sub-path. 3924 * 3925 * The behavior of $(D closePath()) is distinct from simply 3926 * calling $(D lineTo()) with the equivalent coordinate in 3927 * the case of stroking. When a closed sub-path is stroked, 3928 * there are no caps on the ends of the sub-path. Instead, 3929 * there is a line join connecting the final and initial 3930 * segments of the sub-path. 3931 * 3932 * If there is no current point before the call to $(D closePath()), 3933 * this function will have no effect. 3934 * 3935 * Note: As of cairo version 1.2.4 any call to $(D closePath()) 3936 * will place an explicit MOVE_TO element into the path immediately 3937 * after the CLOSE_PATH element, (which can be seen in 3938 * $(D copyPath()) for example). This can simplify path processing 3939 * in some cases as it may not be necessary to save the "last 3940 * move_to point" during processing as the MOVE_TO immediately 3941 * after the CLOSE_PATH will provide that point. 3942 */ 3943 void closePath() 3944 { 3945 cairo_close_path(this.nativePointer); 3946 checkError(); 3947 } 3948 3949 /** 3950 * Adds a circular arc of the given radius to the current path. 3951 * The arc is centered at center, begins at angle1 and proceeds in 3952 * the direction of increasing angles to end at angle2. 3953 * If angle2 is less than angle1 it will be progressively 3954 * increased by 2*PI until it is greater than angle1. 3955 * 3956 * If there is a current point, an initial line segment will be 3957 * added to the path to connect the current point to the beginning 3958 * of the arc. If this initial line is undesired, it can be 3959 * avoided by calling $(D newSubPath()) before calling $(D arc()). 3960 * 3961 * Angles are measured in radians. An angle of 0.0 is in the 3962 * direction of the positive X axis (in user space). An angle 3963 * of PI/2.0 radians (90 degrees) is in the direction of the 3964 * positive Y axis (in user space). Angles increase in the 3965 * direction from the positive X axis toward the positive Y 3966 * axis. So with the default transformation matrix, angles 3967 * increase in a clockwise direction. 3968 * 3969 * (To convert from degrees to radians, use degrees * (PI / 180)) 3970 * 3971 * This function gives the arc in the direction of increasing angles; 3972 * see $(D arcNegative()) to get the arc in the direction of decreasing angles. 3973 * 3974 * The arc is circular in user space. To achieve an elliptical arc, 3975 * you can scale the current transformation matrix by different 3976 * amounts in the X and Y directions. For example, to draw an 3977 * ellipse in the box given by x, y, width, height: 3978 * ------------------- 3979 * cr.save(); 3980 * cr.translate(x + width / 2, y + height / 2); 3981 * cr.scale(width / 2, height / 2); 3982 * cr.arc(Point(0, 0), 1, 0, 2 * PI); 3983 * cr.restore(); 3984 * ------------------- 3985 * Params: 3986 * radius = the radius of the arc 3987 * angle1 = the start angle, in radians 3988 * angle2 = the end angle, in radians 3989 */ 3990 void arc(Point!double center, double radius, double angle1, double angle2) 3991 { 3992 cairo_arc(this.nativePointer, center.x, center.y, radius, angle1, angle2); 3993 checkError(); 3994 } 3995 ///ditto 3996 void arc(double centerX, double centerY, double radius, double angle1, double angle2) 3997 { 3998 cairo_arc(this.nativePointer, centerX, centerY, radius, angle1, angle2); 3999 checkError(); 4000 } 4001 4002 /** 4003 * Adds a circular arc of the given radius to the current path. 4004 * The arc is centered at center, begins at angle1 and proceeds 4005 * in the direction of decreasing angles to end at angle2. 4006 * If angle2 is greater than angle1 it will be progressively 4007 * decreased by 2*PI until it is less than angle1. 4008 * 4009 * See $(D arc()) for more details. This function differs only 4010 * in the direction of the arc between the two angles. 4011 * 4012 * Params: 4013 * radius = the radius of the arc 4014 * angle1 = the start angle, in radians 4015 * angle2 = the end angle, in radians 4016 */ 4017 void arcNegative(Point!double center, double radius, double angle1, double angle2) 4018 { 4019 cairo_arc_negative(this.nativePointer, center.x, center.y, radius, angle1, angle2); 4020 checkError(); 4021 } 4022 ///ditto 4023 void arcNegative(double centerX, double centerY, double radius, double angle1, double angle2) 4024 { 4025 cairo_arc_negative(this.nativePointer, centerX, centerY, radius, angle1, angle2); 4026 checkError(); 4027 } 4028 4029 /** 4030 * Adds a cubic Bézier spline to the path from the current 4031 * point to position p3 in user-space coordinates, using p1 and p2 4032 * as the control points. After this call the current point will be p3. 4033 * 4034 * If there is no current point before the call to $(D curveTo()) 4035 * this function will behave as if preceded by a call to 4036 * $(D moveTo(p1)). 4037 * 4038 * Params: 4039 * p1 = First control point 4040 * p2 = Second control point 4041 * p3 = End of the curve 4042 */ 4043 void curveTo(Point!double p1, Point!double p2, Point!double p3) 4044 { 4045 cairo_curve_to(this.nativePointer, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); 4046 checkError(); 4047 } 4048 ///ditto 4049 void curveTo(double p1x, double p1y, double p2x, double p2y, 4050 double p3x, double p3y) 4051 { 4052 cairo_curve_to(this.nativePointer, p1x, p1y, p2x, p2y, p3x, p3y); 4053 checkError(); 4054 } 4055 4056 /** 4057 * Adds a line to the path from the current point to position p1 4058 * in user-space coordinates. After this call the current point 4059 * will be p1. 4060 * 4061 * If there is no current point before the call to $(D lineTo()) 4062 * this function will behave as $(D moveTo(p1)). 4063 * 4064 * Params: 4065 * p1 = End of the line 4066 */ 4067 void lineTo(Point!double p1) 4068 { 4069 cairo_line_to(this.nativePointer, p1.x, p1.y); 4070 checkError(); 4071 } 4072 ///ditto 4073 void lineTo(double x, double y) 4074 { 4075 cairo_line_to(this.nativePointer, x, y); 4076 checkError(); 4077 } 4078 4079 /** 4080 * Begin a new sub-path. After this call the current point will be p1. 4081 */ 4082 void moveTo(Point!double p1) 4083 { 4084 cairo_move_to(this.nativePointer, p1.x, p1.y); 4085 checkError(); 4086 } 4087 ///ditto 4088 void moveTo(double x, double y) 4089 { 4090 cairo_move_to(this.nativePointer, x, y); 4091 checkError(); 4092 } 4093 4094 /** 4095 * Adds a closed sub-path rectangle of the given size to the 4096 * current path at position r.point in user-space coordinates. 4097 * This function is logically equivalent to: 4098 * --------------------- 4099 * cr.moveTo(r.point); 4100 * cr.relLineTo(r.width, 0); 4101 * cr.relLineTo(0, r.height); 4102 * cr.relLineTo(-r.width, 0); 4103 * cr.closePath(); 4104 * --------------------- 4105 */ 4106 void rectangle(Rectangle!double r) 4107 { 4108 cairo_rectangle(this.nativePointer, r.point.x, r.point.y, r.width, r.height); 4109 checkError(); 4110 } 4111 ///ditto 4112 void rectangle(double x, double y, double width, double height) 4113 { 4114 cairo_rectangle(this.nativePointer, x, y, width, height); 4115 checkError(); 4116 } 4117 4118 /** 4119 * Adds closed paths for the glyphs to the current path. 4120 * The generated path if filled, achieves an effect 4121 * similar to that of $(D showGlyphs()). 4122 */ 4123 void glyphPath(Glyph[] glyphs) 4124 { 4125 cairo_glyph_path(this.nativePointer, glyphs.ptr, glyphs.length.toCairoCount()); 4126 checkError(); 4127 } 4128 4129 /** 4130 * Adds closed paths for text to the current path. The generated 4131 * path if filled, achieves an effect similar to that of 4132 * $(D showText()). 4133 * 4134 * Text conversion and positioning is done similar to $(D showText()). 4135 * 4136 * Like $(D showText()), After this call the current point is moved 4137 * to the origin of where the next glyph would be placed in this 4138 * same progression. That is, the current point will be at the 4139 * origin of the final glyph offset by its advance values. This 4140 * allows for chaining multiple calls to to $(D textPath()) 4141 * without having to set current point in between. 4142 * 4143 * Note: The $(D textPath()) function call is part of what the 4144 * cairo designers call the "toy" text API. It is convenient for 4145 * short demos and simple programs, but it is not expected 4146 * to be adequate for serious text-using applications. See 4147 * $(D glyphPath()) for the "real" text path API in cairo. 4148 */ 4149 void textPath(string text) 4150 { 4151 cairo_text_path(this.nativePointer, toStringz(text)); 4152 checkError(); 4153 } 4154 4155 /** 4156 * Relative-coordinate version of $(D curveTo()). 4157 * All offsets are relative to the current point. Adds a 4158 * cubic Bézier spline to the path from the current point 4159 * to a point offset from the current point by rp3, 4160 * using points offset by rp1 and rp2 as the 4161 * control points. After this call the current point will 4162 * be offset by rp3. 4163 * 4164 * Given a current point of (x, y), 4165 * cairo_rel_curve_to(cr, dx1, dy1, dx2, dy2, dx3, dy3) is logically 4166 * equivalent to 4167 * cairo_curve_to(cr, x+dx1, y+dy1, x+dx2, y+dy2, x+dx3, y+dy3). 4168 * 4169 * It is an error to call this function with no current point. 4170 * Doing so will cause an CairoException with a 4171 * status of CAIRO_STATUS_NO_CURRENT_POINT. 4172 * 4173 * Params: 4174 * rp1 = First control point 4175 * rp2 = Second control point 4176 * rp3 = offset to the end of the curve 4177 */ 4178 void relCurveTo(Point!double rp1, Point!double rp2, Point!double rp3) 4179 { 4180 cairo_rel_curve_to(this.nativePointer, rp1.x, rp1.y, rp2.x, rp2.y, rp3.x, rp3.y); 4181 checkError(); 4182 } 4183 ///ditto 4184 void relCurveTo(double rp1x, double rp1y, double rp2x, double rp2y, 4185 double rp3x, double rp3y) 4186 { 4187 cairo_rel_curve_to(this.nativePointer, rp1x, rp1y, rp2x, rp2y, rp3x, rp3y); 4188 checkError(); 4189 } 4190 4191 /** 4192 * Relative-coordinate version of $(D lineTo()). Adds a line 4193 * to the path from the current point to a point that is 4194 * offset from the current point by rp1 in user space. 4195 * After this call the current point will be offset by rp1. 4196 * 4197 * Given a current point of (x, y), cairo_rel_line_to(cr, dx, dy) 4198 * is logically equivalent to cairo_line_to(cr, x + dx, y + dy). 4199 * 4200 * It is an error to call this function with no current point. 4201 * Doing so will cause an CairoException with a 4202 * status of CAIRO_STATUS_NO_CURRENT_POINT. 4203 */ 4204 void relLineTo(Point!double rp1) 4205 { 4206 cairo_rel_line_to(this.nativePointer, rp1.x, rp1.y); 4207 checkError(); 4208 } 4209 ///ditto 4210 void relLineTo(double x, double y) 4211 { 4212 cairo_rel_line_to(this.nativePointer, x, y); 4213 checkError(); 4214 } 4215 4216 /** 4217 * Begin a new sub-path. After this call the current point will 4218 * offset by rp1. 4219 * 4220 * Given a current point of (x, y), cairo_rel_move_to(cr, dx, dy) 4221 * is logically equivalent to cairo_move_to(cr, x + dx, y + dy). 4222 * 4223 * It is an error to call this function with no current point. 4224 * Doing so will cause an CairoException with a status of 4225 * CAIRO_STATUS_NO_CURRENT_POINT. 4226 */ 4227 void relMoveTo(Point!double rp1) 4228 { 4229 cairo_rel_move_to(this.nativePointer, rp1.x, rp1.y); 4230 checkError(); 4231 } 4232 ///ditto 4233 void relMoveTo(double x, double y) 4234 { 4235 cairo_rel_move_to(this.nativePointer, x, y); 4236 checkError(); 4237 } 4238 4239 /** 4240 * Computes a bounding box in user-space coordinates covering 4241 * the points on the current path. If the current path is empty, 4242 * returns an empty Box ((0,0), (0,0)). Stroke parameters, 4243 * fill rule, surface dimensions and clipping are not taken 4244 * into account. 4245 * 4246 * Contrast with $(D fillExtents()) and $(D strokeExtents()) 4247 * which return the extents of only the area that would be "inked" 4248 * by the corresponding drawing operations. 4249 * 4250 * The result of $(D pathExtents()) is defined as equivalent 4251 * to the limit of $(D strokeExtents()) with CAIRO_LINE_CAP_ROUND 4252 * as the line width approaches 0.0, (but never reaching the 4253 * empty-rectangle returned by $(D strokeExtents()) for a 4254 * line width of 0.0). 4255 * 4256 * Specifically, this means that zero-area sub-paths such as 4257 * $(D moveTo());$(D lineTo()) segments, (even degenerate 4258 * cases where the coordinates to both calls are identical), 4259 * will be considered as contributing to the extents. However, 4260 * a lone $(D moveTo()) will not contribute to the 4261 * results of $(D pathExtents()). 4262 */ 4263 Box pathExtends() 4264 { 4265 Box tmp; 4266 cairo_path_extents(this.nativePointer, &tmp.point1.x, &tmp.point1.y, &tmp.point2.x, &tmp.point2.y); 4267 checkError(); 4268 return tmp; 4269 } 4270 4271 /** 4272 * Modifies the current transformation matrix (CTM) by translating 4273 * the user-space origin by (tx, ty). This offset is interpreted 4274 * as a user-space coordinate according to the CTM in place 4275 * before the new call to $(D translate()). In other words, 4276 * the translation of the user-space origin takes place 4277 * after any existing transformation. 4278 * 4279 * Params: 4280 * tx = amount to translate in the X direction 4281 * ty = amount to translate in the Y direction 4282 */ 4283 void translate(double tx, double ty) 4284 { 4285 cairo_translate(this.nativePointer, tx, ty); 4286 checkError(); 4287 } 4288 4289 /** 4290 * Modifies the current transformation matrix (CTM) by scaling 4291 * the X and Y user-space axes by sx and sy respectively. 4292 * The scaling of the axes takes place after any existing 4293 * transformation of user space. 4294 * 4295 * Params: 4296 * sx = scale factor for the X dimension 4297 * sy = scale factor for the Y dimension 4298 */ 4299 void scale(double sx, double sy) 4300 { 4301 cairo_scale(this.nativePointer, sx, sy); 4302 checkError(); 4303 } 4304 4305 ///ditto 4306 void scale(Point!double point) 4307 { 4308 scale(point.x, point.y); 4309 } 4310 4311 /** 4312 * Modifies the current transformation matrix (CTM) by rotating 4313 * the user-space axes by angle radians. The rotation of the 4314 * axes takes places after any existing transformation of user 4315 * space. The rotation direction for positive angles is from 4316 * the positive X axis toward the positive Y axis. 4317 * 4318 * Params: 4319 * angle = angle (in radians) by which the user-space axes will be rotated 4320 */ 4321 void rotate(double angle) 4322 { 4323 cairo_rotate(this.nativePointer, angle); 4324 checkError(); 4325 } 4326 4327 /** 4328 * Modifies the current transformation matrix (CTM) by applying 4329 * matrix as an additional transformation. The new 4330 * transformation of user space takes place after any 4331 * existing transformation. 4332 * 4333 * Params: 4334 * matrix = a transformation to be applied to the user-space axes 4335 */ 4336 void transform(const Matrix matrix) 4337 { 4338 cairo_transform(this.nativePointer, &matrix.nativeMatrix); 4339 checkError(); 4340 } 4341 4342 /** 4343 * Modifies the current transformation matrix (CTM) by setting it 4344 * equal to matrix. 4345 * 4346 * Params: 4347 * Matrix = a transformation matrix from user space to device space 4348 */ 4349 void setMatrix(const Matrix matrix) 4350 { 4351 cairo_set_matrix(this.nativePointer, &matrix.nativeMatrix); 4352 checkError(); 4353 } 4354 4355 /** 4356 * Returns the current transformation matrix (CTM) 4357 */ 4358 Matrix getMatrix() 4359 { 4360 Matrix m; 4361 cairo_get_matrix(this.nativePointer, &m.nativeMatrix); 4362 checkError(); 4363 return m; 4364 } 4365 4366 ///Convenience property 4367 @property void matrix(const Matrix matrix) 4368 { 4369 setMatrix(matrix); 4370 } 4371 4372 ///ditto 4373 @property Matrix matrix() 4374 { 4375 return getMatrix(); 4376 } 4377 4378 /** 4379 * Resets the current transformation matrix (CTM) by setting it 4380 * equal to the identity matrix. That is, the user-space and 4381 * device-space axes will be aligned and one user-space unit 4382 * will transform to one device-space unit. 4383 */ 4384 void identityMatrix() 4385 { 4386 cairo_identity_matrix(this.nativePointer); 4387 checkError(); 4388 } 4389 4390 /** 4391 * Transform a coordinate from user space to device space by 4392 * multiplying the given point by the current 4393 * transformation matrix (CTM). 4394 */ 4395 Point!double userToDevice(Point!double inp) 4396 { 4397 cairo_user_to_device(this.nativePointer, &inp.x, &inp.y); 4398 checkError(); 4399 return inp; 4400 } 4401 4402 /** 4403 * Transform a distance vector from user space to device space. 4404 * This function is similar to $(D userToDevice()) except that 4405 * the translation components of the CTM will be ignored when 4406 * transforming inp. 4407 */ 4408 Point!double userToDeviceDistance(Point!double inp) 4409 { 4410 cairo_user_to_device_distance(this.nativePointer, &inp.x, &inp.y); 4411 checkError(); 4412 return inp; 4413 } 4414 4415 /** 4416 * Transform a coordinate from device space to user space by 4417 * multiplying the given point by the inverse of the current 4418 * transformation matrix (CTM). 4419 */ 4420 Point!double deviceToUser(Point!double inp) 4421 { 4422 cairo_device_to_user(this.nativePointer, &inp.x, &inp.y); 4423 checkError(); 4424 return inp; 4425 } 4426 4427 /** 4428 * Transform a distance vector from device space to user space. 4429 * This function is similar to $(D deviceToUser()) except that 4430 * the translation components of the inverse CTM will be ignored 4431 * when transforming inp. 4432 */ 4433 Point!double deviceToUserDistance(Point!double inp) 4434 { 4435 cairo_device_to_user_distance(this.nativePointer, &inp.x, &inp.y); 4436 checkError(); 4437 return inp; 4438 } 4439 4440 /** 4441 * Note: The $(D selectFontFace()) function call is part of 4442 * what the cairo designers call the "toy" text API. It 4443 * is convenient for short demos and simple programs, but 4444 * it is not expected to be adequate for serious text-using 4445 * applications. 4446 * 4447 * Selects a family and style of font from a simplified description 4448 * as a family name, slant and weight. Cairo provides no 4449 * operation to list available family names on the system 4450 * (this is a "toy", remember), but the standard CSS2 generic 4451 * family names, ("serif", "sans-serif", "cursive", "fantasy", 4452 * "monospace"), are likely to work as expected. 4453 * 4454 * If family starts with the string "cairo:", or if no native 4455 * font backends are compiled in, cairo will use an internal 4456 * font family. The internal font family recognizes many 4457 * modifiers in the family string, most notably, it recognizes 4458 * the string "monospace". That is, the family name 4459 * "cairo:monospace" will use the monospace version of the 4460 * internal font family. 4461 * 4462 * For "real" font selection, see the font-backend-specific 4463 * $(D FontFace) classes for the font backend you are using. 4464 * (For example, if you are using the freetype-based cairo-ft 4465 * font backend, see $(D FTFontFace)) 4466 * 4467 * The resulting font face could then be used 4468 * with $(D ScaledFont) and $(D Context.setScaledFont()). 4469 * 4470 * Similarly, when using the "real" font support, you can call 4471 * directly into the underlying font system, (such as 4472 * fontconfig or freetype), for operations such as listing 4473 * available fonts, etc. 4474 * 4475 * It is expected that most applications will need to use a more 4476 * comprehensive font handling and text layout library, 4477 * (for example, pango), in conjunction with cairo. 4478 * 4479 * If text is drawn without a call to $(D selectFontFace()), 4480 * (nor $(D setFontFace()) nor $(D setScaledFont())), 4481 * the default family is platform-specific, but is essentially 4482 * "sans-serif". Default slant is CAIRO_FONT_SLANT_NORMAL, 4483 * and default weight is CAIRO_FONT_WEIGHT_NORMAL. 4484 * 4485 * This function is equivalent to a call to 4486 * $(D toyFontFaceCreate()) followed by $(D setFontFace()). 4487 * 4488 * Params: 4489 * family = a font family name, encoded in UTF-8 4490 * slant = the slant for the font 4491 * weight = the weight for the font 4492 */ 4493 void selectFontFace(string family, FontSlant slant, FontWeight weight) 4494 { 4495 cairo_select_font_face(this.nativePointer, toStringz(family), slant, weight); 4496 checkError(); 4497 } 4498 4499 /** 4500 * Sets the current font matrix to a scale by a factor of size, 4501 * replacing any font matrix previously set with $(D setFontSize()) 4502 * or $(D setFontMatrix()). This results in a font size of 4503 * size user space units. (More precisely, this matrix will 4504 * result in the font's em-square being a size by size 4505 * square in user space.) 4506 * 4507 * If text is drawn without a call to $(D setFontSize()), 4508 * (nor $(D setFontMatrix()) nor $(D setScaledFont())), 4509 * the default font size is 10.0. 4510 * 4511 * Params: 4512 * size = the new font size, in user space units 4513 */ 4514 void setFontSize(double size) 4515 { 4516 cairo_set_font_size(this.nativePointer, size); 4517 checkError(); 4518 } 4519 4520 /** 4521 * Sets the current font matrix to matrix. The font matrix gives 4522 * a transformation from the design space of the font (in this 4523 * space, the em-square is 1 unit by 1 unit) to user space. 4524 * Normally, a simple scale is used (see $(D setFontSize())), 4525 * but a more complex font matrix can be used to shear the font 4526 * or stretch it unequally along the two axes 4527 * 4528 * Params: 4529 * matrix = a $(D Matrix) describing a transform to be applied 4530 * to the current font. 4531 */ 4532 void setFontMatrix(Matrix matrix) 4533 { 4534 cairo_set_font_matrix(this.nativePointer, &matrix.nativeMatrix); 4535 checkError(); 4536 } 4537 4538 /** 4539 * Returns the current font matrix. See $(D setFontMatrix). 4540 */ 4541 Matrix getFontMatrix() 4542 { 4543 Matrix res; 4544 cairo_get_font_matrix(this.nativePointer, &res.nativeMatrix); 4545 checkError(); 4546 return res; 4547 } 4548 4549 ///Convenience property 4550 @property void fontMatrix(Matrix matrix) 4551 { 4552 setFontMatrix(matrix); 4553 } 4554 4555 ///ditto 4556 @property Matrix fontMatrix() 4557 { 4558 return getFontMatrix(); 4559 } 4560 4561 /** 4562 * Sets a set of custom font rendering options for the 4563 * $(D Context). Rendering options are derived by merging these 4564 * options with the options derived from underlying surface; 4565 * if the value in options has a default value (like CAIRO_ANTIALIAS_DEFAULT), 4566 * then the value from the surface is used. 4567 */ 4568 void setFontOptions(FontOptions options) 4569 { 4570 cairo_set_font_options(this.nativePointer, options.nativePointer); 4571 checkError(); 4572 } 4573 4574 /** 4575 * Retrieves font rendering options set via $(D setFontOptions()). 4576 * Note that the returned options do not include any options 4577 * derived from the underlying surface; they are literally 4578 * the options passed to $(D setFontOptions()). 4579 */ 4580 FontOptions getFontOptions() 4581 { 4582 auto opt = FontOptions.create(); 4583 cairo_get_font_options(this.nativePointer, opt.nativePointer); 4584 checkError(); 4585 return opt; 4586 } 4587 4588 ///Convenience property 4589 @property void fontOptions(FontOptions options) 4590 { 4591 setFontOptions(options); 4592 } 4593 4594 ///ditto 4595 @property FontOptions fontOptions() 4596 { 4597 return getFontOptions(); 4598 } 4599 4600 /** 4601 * Replaces the current $(D FontFace) object in the $(D Context) 4602 * with font_face. The replaced font face in the $(D Context) will 4603 * be destroyed if there are no other references to it. 4604 */ 4605 void setFontFace(FontFace font_face) 4606 { 4607 cairo_set_font_face(this.nativePointer, font_face.nativePointer); 4608 checkError(); 4609 } 4610 4611 /** 4612 * Replaces the current $(D FontFace) object in the $(D Context) 4613 * with the default font. 4614 */ 4615 void setFontFace() 4616 { 4617 cairo_set_font_face(this.nativePointer, null); 4618 checkError(); 4619 } 4620 4621 // todo: setFontFace should be renamed to resetFontFace, using alias 4622 // instead for backwards-compatibility. 4623 ///convenience alias 4624 alias setFontFace resetFontFace; 4625 4626 /** 4627 * Gets the current font face for a $(D Context). 4628 */ 4629 FontFace getFontFace() 4630 { 4631 return FontFace.createFromNative(cairo_get_font_face(this.nativePointer)); 4632 } 4633 4634 ///Convenience property 4635 @property void fontFace(FontFace font_face) 4636 { 4637 setFontFace(font_face); 4638 } 4639 4640 ///ditto 4641 @property FontFace fontFace() 4642 { 4643 return getFontFace(); 4644 } 4645 4646 /** 4647 * Replaces the current font face, font matrix, and font options 4648 * in the $(D Context) with those of the $(D ScaledFont). Except 4649 * for some translation, the current CTM of the cairo_t should be 4650 * the same as that of the $(D ScaledFont), which can be 4651 * accessed using $(D ScaledFont.getCTM()). 4652 */ 4653 void setScaledFont(ScaledFont scaled_font) 4654 { 4655 cairo_set_scaled_font(this.nativePointer, scaled_font.nativePointer); 4656 checkError(); 4657 } 4658 4659 /** 4660 * Gets the current scaled font for a $(D Context). 4661 */ 4662 ScaledFont getScaledFont() 4663 { 4664 return ScaledFont.createFromNative(cairo_get_scaled_font(this.nativePointer)); 4665 } 4666 4667 ///Convenience property 4668 @property void scaledFont(ScaledFont scaled_font) 4669 { 4670 setScaledFont(scaled_font); 4671 } 4672 4673 ///ditto 4674 @property ScaledFont scaledFont() 4675 { 4676 return getScaledFont(); 4677 } 4678 4679 /** 4680 * A drawing operator that generates the shape from a string of 4681 * UTF-8 characters, rendered according to the current 4682 * fontFace, fontSize (fontMatrix), and fontOptions. 4683 * 4684 * This function first computes a set of glyphs for the string 4685 * of text. The first glyph is placed so that its origin is 4686 * at the current point. The origin of each subsequent glyph 4687 * is offset from that of the previous glyph by the advance 4688 * values of the previous glyph. 4689 * 4690 * After this call the current point is moved to the origin 4691 * of where the next glyph would be placed in this same 4692 * progression. That is, the current point will be at the 4693 * origin of the final glyph offset by its advance values. 4694 * This allows for easy display of a single logical string 4695 * with multiple calls to $(D showText()). 4696 * 4697 * Note: The $(D showText()) function call is part of 4698 * what the cairo designers call the "toy" text API. It 4699 * is convenient for short demos and simple programs, but 4700 * it is not expected to be adequate for serious text-using 4701 * applications. See $(D showGlyphs()) for the "real" text 4702 * display API in cairo. 4703 */ 4704 void showText(string text) 4705 { 4706 cairo_show_text(this.nativePointer, toStringz(text)); 4707 checkError(); 4708 } 4709 4710 /** 4711 * A drawing operator that generates the shape from an array of 4712 * glyphs, rendered according to the current fontFace, 4713 * fontSize (fontMatrix), and font options. 4714 */ 4715 void showGlyphs(Glyph[] glyphs) 4716 { 4717 cairo_show_glyphs(this.nativePointer, glyphs.ptr, glyphs.length.toCairoCount()); 4718 checkError(); 4719 } 4720 4721 /** 4722 * This operation has rendering effects similar to $(D showGlyphs()) 4723 * but, if the target surface supports it, uses the provided 4724 * text and cluster mapping to embed the text for the glyphs 4725 * shown in the output. If the target does not support the 4726 * extended attributes, this function acts like the basic 4727 * $(D showGlyphs()). 4728 */ 4729 void showTextGlyphs(TextGlyph glyph) 4730 { 4731 cairo_show_text_glyphs(this.nativePointer, glyph.text.ptr, 4732 glyph.text.length.toCairoCount(), glyph.glyphs.ptr, glyph.glyphs.length.toCairoCount(), 4733 glyph.cluster.ptr, glyph.cluster.length.toCairoCount(), glyph.flags); 4734 checkError(); 4735 } 4736 4737 /** 4738 * Gets the font extents for the currently selected font. 4739 */ 4740 FontExtents fontExtents() 4741 { 4742 FontExtents res; 4743 cairo_font_extents(this.nativePointer, &res); 4744 checkError(); 4745 return res; 4746 } 4747 4748 /** 4749 * Gets the extents for a string of text. The extents describe 4750 * a user-space rectangle that encloses the "inked" 4751 * portion of the text, (as it would be drawn by $(D showText())). 4752 * Additionally, the x_advance and y_advance values indicate 4753 * the amount by which the current point would be advanced 4754 * by $(D showText()). 4755 * 4756 * Note that whitespace characters do not directly contribute 4757 * to the size of the rectangle (extents.width and extents.height). 4758 * They do contribute indirectly by changing the position of 4759 * non-whitespace characters. In particular, trailing whitespace 4760 * characters are likely to not affect the size of the rectangle, 4761 * though they will affect the x_advance and y_advance values. 4762 */ 4763 TextExtents textExtents(string text) 4764 { 4765 TextExtents res; 4766 cairo_text_extents(this.nativePointer, toStringz(text), &res); 4767 checkError(); 4768 return res; 4769 } 4770 4771 /** 4772 * Gets the extents for an array of glyphs. The extents describe 4773 * a user-space rectangle that encloses the "inked" portion of 4774 * the glyphs, (as they would be drawn by $(D showGlyphs())). 4775 * Additionally, the x_advance and y_advance values indicate 4776 * the amount by which the current point would be advanced by 4777 * $(D showGlyphs()). 4778 * 4779 * Note that whitespace glyphs do not contribute to the size of 4780 * the rectangle (extents.width and extents.height). 4781 */ 4782 TextExtents glyphExtents(Glyph[] glyphs) 4783 { 4784 TextExtents res; 4785 cairo_glyph_extents(this.nativePointer, glyphs.ptr, glyphs.length.toCairoCount(), &res); 4786 checkError(); 4787 return res; 4788 } 4789 } 4790 4791 /* ------------------------------- Fonts ------------------------------ */ 4792 4793 /** 4794 * $(D FontOptions) - How a font should be rendered 4795 * 4796 * The font options specify how fonts should be rendered. Most of the 4797 * time the font options implied by a surface are just right and do 4798 * not need any changes, but for pixel-based targets tweaking font 4799 * options may result in superior output on a particular display. 4800 * 4801 * Warning: Instances must be created with the create static member function! 4802 * -------- 4803 * auto options = FontOptions.create(); //Correct 4804 * options.toHash(); 4805 * -------- 4806 * 4807 * -------- 4808 * FontOptions options; //Wrong 4809 * options.toHash(); 4810 * -------- 4811 * 4812 * -------- 4813 * FontOptions options; 4814 * options = FontOptions.create(); //Correct 4815 * options.toHash(); 4816 * -------- 4817 */ 4818 public struct FontOptions 4819 { 4820 private: 4821 struct Payload 4822 { 4823 cairo_font_options_t* _payload; 4824 this(cairo_font_options_t* h) 4825 { 4826 _payload = h; 4827 } 4828 ~this() 4829 { 4830 if(_payload) 4831 { 4832 cairo_font_options_destroy(_payload); 4833 _payload = null; 4834 } 4835 } 4836 4837 // Should never perform these operations 4838 this(this) { assert(false); } 4839 void opAssign(FontOptions.Payload rhs) { assert(false); } 4840 } 4841 4842 alias RefCounted!(Payload, RefCountedAutoInitialize.no) Data; 4843 Data _data; 4844 4845 protected: 4846 final void checkError() 4847 { 4848 throwError(cairo_font_options_status(nativePointer)); 4849 } 4850 4851 public: 4852 /** 4853 * The underlying $(D cairo_font_options_t*) handle 4854 */ 4855 @property cairo_font_options_t* nativePointer() 4856 { 4857 return _data._payload; 4858 } 4859 4860 version(D_Ddoc) 4861 { 4862 /** 4863 * Enable / disable memory management debugging for this FontOptions 4864 * instance. Only available if both cairoD and the cairoD user 4865 * code were compiled with "debug=RefCounted" 4866 * 4867 * Output is written to stdout, see 4868 * $(LINK https://github.com/jpf91/cairoD/wiki/Memory-Management#debugging) 4869 * for more information 4870 */ 4871 @property bool debugging(); 4872 ///ditto 4873 @property void debugging(bool value); 4874 } 4875 else debug(RefCounted) 4876 { 4877 @property bool debugging() 4878 { 4879 return _data.RefCounted.debugging; 4880 } 4881 4882 @property void debugging(bool value) 4883 { 4884 _data.RefCounted.debugging = value; 4885 } 4886 } 4887 4888 /** 4889 * Allocates a new font options object with all 4890 * options initialized to default values. 4891 */ 4892 static FontOptions create() 4893 { 4894 FontOptions opt; 4895 auto ptr = cairo_font_options_create(); 4896 throwError(cairo_font_options_status(ptr)); 4897 opt._data = Data(ptr); 4898 return opt; 4899 } 4900 4901 /** 4902 * Create $(D FontOptions) from a existing $(D cairo_font_options_t*). 4903 * FontOptions is a reference counted struct. It will call 4904 * $(D cairo_font_options_destroy) when it's reference count is 0. 4905 * See $(LINK https://github.com/jpf91/cairoD/wiki/Memory-Management#2.2-structs) 4906 * for more information. 4907 * 4908 * Warning: 4909 * $(RED Only use this if you know what your doing! 4910 * This function should not be needed for standard cairoD usage.) 4911 */ 4912 this(cairo_font_options_t* ptr) 4913 { 4914 if(!ptr) 4915 { 4916 throw new CairoException(cairo_status_t.CAIRO_STATUS_NULL_POINTER); 4917 } 4918 throwError(cairo_font_options_status(ptr)); 4919 _data = Data(ptr); 4920 } 4921 4922 /** 4923 * Allocates a new font options object copying the option values 4924 * from original. 4925 * 4926 * This new object's reference counting is independent from the 4927 * current object's. 4928 */ 4929 FontOptions copy() 4930 { 4931 return FontOptions(cairo_font_options_copy(nativePointer)); 4932 } 4933 4934 /** 4935 * Merges non-default options from other into this object, 4936 * replacing existing values. This operation can be thought 4937 * of as somewhat similar to compositing other onto options 4938 * with the operation of CAIRO_OPERATION_OVER. 4939 */ 4940 void merge(FontOptions other) 4941 { 4942 cairo_font_options_merge(nativePointer, other.nativePointer); 4943 checkError(); 4944 } 4945 4946 /** 4947 * Compute a hash for the font options object; this value 4948 * will be useful when storing an object containing a 4949 * FontOptions in a hash table. 4950 */ 4951 /* 4952 * Cairo docs say hash can be casted to a 32bit value, if needed 4953 */ 4954 size_t toHash() 4955 { 4956 auto hash = cast(size_t)cairo_font_options_hash(nativePointer); 4957 checkError(); 4958 return hash; 4959 } 4960 4961 /** 4962 * Compares two font options objects for equality. 4963 * 4964 * Returns: 4965 * true if all fields of the two font options objects match. 4966 * Note that this function will return false if either object is 4967 * in error. 4968 */ 4969 const bool opEquals(ref const(FontOptions) other) 4970 { 4971 return cairo_font_options_equal((cast(FontOptions)this).nativePointer, 4972 (cast(FontOptions)other).nativePointer) ? true : false; 4973 } 4974 4975 /** 4976 * Sets the antialiasing mode for the font options object. This 4977 * specifies the type of antialiasing to do when rendering text. 4978 */ 4979 void setAntiAlias(AntiAlias antialias) 4980 { 4981 cairo_font_options_set_antialias(nativePointer, antialias); 4982 checkError(); 4983 } 4984 4985 /** 4986 * Gets the antialiasing mode for the font options object. 4987 */ 4988 AntiAlias getAntiAlias() 4989 { 4990 scope(exit) 4991 checkError(); 4992 return cairo_font_options_get_antialias(nativePointer); 4993 } 4994 4995 ///Convenience property 4996 @property void antiAlias(AntiAlias aa) 4997 { 4998 setAntiAlias(aa); 4999 } 5000 5001 ///ditto 5002 @property AntiAlias antiAlias() 5003 { 5004 return getAntiAlias(); 5005 } 5006 5007 /** 5008 * Sets the subpixel order for the font options object. 5009 * The subpixel order specifies the order of color elements 5010 * within each pixel on the display device when rendering with 5011 * an antialiasing mode of CAIRO_ANTIALIAS_SUBPIXEL. 5012 * See the documentation for $(D SubpixelOrder) for full details. 5013 */ 5014 void setSubpixelOrder(SubpixelOrder order) 5015 { 5016 cairo_font_options_set_subpixel_order(nativePointer, order); 5017 checkError(); 5018 } 5019 5020 /** 5021 * Gets the subpixel order for the font options object. 5022 * See the documentation for $(D SubpixelOrder) for full details. 5023 */ 5024 SubpixelOrder getSubpixelOrder() 5025 { 5026 scope(exit) 5027 checkError(); 5028 return cairo_font_options_get_subpixel_order(nativePointer); 5029 } 5030 5031 ///convenience alias 5032 alias getSubpixelOrder subpixelOrder; 5033 5034 /** 5035 * Sets the hint style for font outlines for the font options object. 5036 * This controls whether to fit font outlines to the pixel grid, 5037 * and if so, whether to optimize for fidelity or contrast. 5038 * See the documentation for $(D HintStyle) for full details. 5039 */ 5040 void setHintStyle(HintStyle style) 5041 { 5042 cairo_font_options_set_hint_style(nativePointer, style); 5043 checkError(); 5044 } 5045 5046 /** 5047 * Gets the hint style for font outlines for the font options object. 5048 * See the documentation for $(D HintStyle) for full details. 5049 */ 5050 HintStyle getHintStyle() 5051 { 5052 scope(exit) 5053 checkError(); 5054 return cairo_font_options_get_hint_style(nativePointer); 5055 } 5056 5057 ///Convenience property 5058 @property void hintStyle(HintStyle style) 5059 { 5060 setHintStyle(style); 5061 } 5062 5063 ///ditto 5064 @property HintStyle hintStyle() 5065 { 5066 return getHintStyle(); 5067 } 5068 5069 /** 5070 * Sets the metrics hinting mode for the font options object. 5071 * This controls whether metrics are quantized to integer 5072 * values in device units. See the documentation for 5073 * $(D HintMetrics) for full details. 5074 */ 5075 void setHintMetrics(HintMetrics metrics) 5076 { 5077 cairo_font_options_set_hint_metrics(nativePointer, metrics); 5078 checkError(); 5079 } 5080 5081 /** 5082 * Gets the metrics hinting mode for the font options object. 5083 * See the documentation for $(D HintMetrics) for full details. 5084 */ 5085 HintMetrics getHintMetrics() 5086 { 5087 scope(exit) 5088 checkError(); 5089 return cairo_font_options_get_hint_metrics(nativePointer); 5090 } 5091 5092 ///Convenience property 5093 @property void hintMetrics(HintMetrics metrics) 5094 { 5095 setHintMetrics(metrics); 5096 } 5097 5098 ///ditto 5099 @property HintMetrics hintMetrics() 5100 { 5101 return getHintMetrics(); 5102 } 5103 } 5104 5105 /** 5106 * The mapping between utf8 and glyphs is provided by an array 5107 * of clusters. Each cluster covers a number of text bytes and 5108 * glyphs, and neighboring clusters cover neighboring areas of 5109 * utf8 and glyphs. The clusters should collectively cover 5110 * utf8 and glyphs in entirety. 5111 * 5112 * The first cluster always covers bytes from the beginning of 5113 * utf8. If cluster_flags do not have the 5114 * CAIRO_TEXT_CLUSTER_FLAG_BACKWARD set, the first cluster also 5115 * covers the beginning of glyphs, otherwise it covers the end 5116 * of the glyphs array and following clusters move backward. 5117 * 5118 * See cairo_text_cluster_t for constraints on valid clusters. 5119 */ 5120 public struct TextGlyph 5121 { 5122 public: 5123 ///array of glyphs 5124 Glyph[] glyphs; 5125 ///array of cluster mapping information 5126 TextCluster[] cluster; 5127 ///a string of text encoded in UTF-8 5128 string text; 5129 ///cluster mapping flags 5130 TextClusterFlags flags; 5131 } 5132 5133 /** 5134 * Font face at particular size and options 5135 * 5136 * $(D ScaledFont) represents a realization of a font face at a particular 5137 * size and transformation and a certain set of font options. 5138 */ 5139 public class ScaledFont 5140 { 5141 /// 5142 mixin CairoCountedClass!(cairo_scaled_font_t*, "cairo_scaled_font_"); 5143 5144 protected: 5145 /** 5146 * Method for use in subclasses. 5147 * Calls $(D cairo_scaled_font_status(nativePointer)) and throws 5148 * an exception if the status isn't CAIRO_STATUS_SUCCESS 5149 */ 5150 final void checkError() 5151 { 5152 throwError(cairo_scaled_font_status(nativePointer)); 5153 } 5154 5155 public: 5156 /** 5157 * Create a $(D ScaledFont) from a existing $(D cairo_scaled_font_t*). 5158 * ScaledFont is a garbage collected class. It will call $(D cairo_scaled_font_destroy) 5159 * when it gets collected by the GC or when $(D dispose()) is called. 5160 * 5161 * Warning: 5162 * $(D ptr)'s reference count is not increased by this function! 5163 * Adjust reference count before calling it if necessary 5164 * 5165 * $(RED Only use this if you know what your doing! 5166 * This function should not be needed for standard cairoD usage.) 5167 */ 5168 this(cairo_scaled_font_t* ptr) 5169 { 5170 this.nativePointer = ptr; 5171 checkError(); 5172 } 5173 5174 /** 5175 * Creates a $(D ScaledFont) object from a font face and 5176 * matrices that describe the size of the font and the 5177 * environment in which it will be used. 5178 * 5179 * Params: 5180 * font_matrix = font space to user space transformation matrix 5181 * for the font. In the simplest case of a N point font, this 5182 * matrix is just a scale by N, but it can also be used to 5183 * shear the font or stretch it unequally along the two axes. 5184 * See $(D Context.setFontMatrix()). 5185 * ctm = user to device transformation matrix with which 5186 * the font will be used. 5187 */ 5188 this(FontFace font_face, Matrix font_matrix, Matrix ctm, 5189 FontOptions options) 5190 { 5191 this(cairo_scaled_font_create(font_face.nativePointer, 5192 &font_matrix.nativeMatrix, &ctm.nativeMatrix, options.nativePointer)); 5193 } 5194 5195 /** 5196 * The createFromNative method for the ScaledFont classes. 5197 * See $(LINK https://github.com/jpf91/cairoD/wiki/Memory-Management#createFromNative) 5198 * for more information. 5199 * 5200 * Warning: 5201 * $(RED Only use this if you know what your doing! 5202 * This function should not be needed for standard cairoD usage.) 5203 */ 5204 static ScaledFont createFromNative(cairo_scaled_font_t* ptr, bool adjRefCount = true) 5205 { 5206 if(!ptr) 5207 { 5208 throw new CairoException(cairo_status_t.CAIRO_STATUS_NULL_POINTER); 5209 } 5210 throwError(cairo_scaled_font_status(ptr)); 5211 //Adjust reference count 5212 if(adjRefCount) 5213 cairo_scaled_font_reference(ptr); 5214 switch(cairo_scaled_font_get_type(ptr)) 5215 { 5216 static if(CAIRO_HAS_WIN32_FONT) 5217 { 5218 import cairo.win32; 5219 case cairo_font_type_t.CAIRO_FONT_TYPE_WIN32: 5220 return new Win32ScaledFont(ptr); 5221 } 5222 static if(CAIRO_HAS_FT_FONT) 5223 { 5224 import cairo.ft; 5225 case cairo_font_type_t.CAIRO_FONT_TYPE_FT: 5226 return new FTScaledFont(ptr); 5227 } 5228 default: 5229 return new ScaledFont(ptr); 5230 } 5231 } 5232 5233 /** 5234 * Gets the metrics for a $(D ScaledFont). 5235 */ 5236 FontExtents extents() 5237 { 5238 FontExtents res; 5239 cairo_scaled_font_extents(this.nativePointer, &res); 5240 checkError(); 5241 return res; 5242 } 5243 5244 /** 5245 * Gets the extents for a string of text. The extents describe a 5246 * user-space rectangle that encloses the "inked" portion of the 5247 * text drawn at the origin (0,0) (as it would be drawn by 5248 * $(D Context.showText()) if the cairo graphics state were set 5249 * to the same fontFace, fontMatrix, ctm, and fontOptions 5250 * as $(D ScaledFont)). Additionally, the x_advance and y_advance 5251 * values indicate the amount by which the current point would 5252 * be advanced by $(D Context.showText()). 5253 * 5254 * Note that whitespace characters do not directly contribute 5255 * to the size of the rectangle (extents.width and extents.height). 5256 * They do contribute indirectly by changing the position of 5257 * non-whitespace characters. In particular, trailing whitespace 5258 * characters are likely to not affect the size of the 5259 * rectangle, though they will affect the x_advance 5260 * and y_advance values. 5261 */ 5262 TextExtents textExtents(string text) 5263 { 5264 TextExtents res; 5265 cairo_scaled_font_text_extents(this.nativePointer, toStringz(text), 5266 &res); 5267 checkError(); 5268 return res; 5269 } 5270 5271 /** 5272 * Gets the extents for an array of glyphs. The extents describe 5273 * a user-space rectangle that encloses the "inked" portion 5274 * of the glyphs, (as they would be drawn by $(D Context.showGlyphs()) 5275 * if the cairo graphics state were set to the same fontFace, 5276 * fontMatrix, ctm, and fontOptions as scaled_font). Additionally, 5277 * the x_advance and y_advance values indicate the amount by 5278 * which the current point would be advanced by $(D Context.showGlyphs()). 5279 * 5280 * Note that whitespace glyphs do not contribute to the size 5281 * of the rectangle (extents.width and extents.height). 5282 */ 5283 TextExtents glyphExtents(Glyph[] glyphs) 5284 { 5285 TextExtents res; 5286 cairo_scaled_font_glyph_extents(this.nativePointer, glyphs.ptr, 5287 glyphs.length.toCairoCount(), &res); 5288 checkError(); 5289 return res; 5290 } 5291 5292 /** 5293 * Converts UTF-8 text to an array of glyphs, optionally with 5294 * cluster mapping, that can be used to render later using ScaledFont. 5295 * 5296 * If glyphBuffer initially points to a non-empty array, that array is 5297 * used as a glyph buffer. If the provided glyph array is too 5298 * short for the conversion, a new glyph array is allocated and returned. 5299 * 5300 * If clusterBuffer is not empty a cluster mapping will be computed. 5301 * The semantics of how cluster array allocation works is similar to the glyph array. 5302 * That is, if clusterBuffer initially points to a non-empty array, 5303 * that array is used as a cluster buffer. 5304 * If the provided cluster array is too short for the conversion, 5305 * a new cluster array is allocated and returned. 5306 * 5307 * In the simplest case, glyphs and clusters can be omitted 5308 * or set to an empty array and a suitable array will be allocated. 5309 * In code 5310 * ----------------- 5311 * auto glyphs = scaled_font.textToTextGlyph(x, y, text); 5312 * cr.showTextGlyphs(glyphs); 5313 * ----------------- 5314 * If no cluster mapping is needed 5315 * ----------------- 5316 * auto glyphs = scaled_font.textToGlyphs(x, y, text); 5317 * cr.showGlyphs(glyphs); 5318 * ----------------- 5319 * If stack-based glyph and cluster arrays are to be used for small arrays 5320 * ----------------- 5321 * Glyph[40] stack_glyphs; 5322 * TextCluster[40] stack_clusters; 5323 * auto glyphs = scaled_font.textToTextGlyph(x, y, text, stack_glyphs, stack_clusters); 5324 * cr.showTextGlyphs(glyphs); 5325 * ----------------- 5326 * 5327 * The output values can be readily passed to $(D Context.showTextGlyphs()) 5328 * $(D Context.showGlyphs()), or related functions, assuming that 5329 * the exact same ScaledFont is used for the operation. 5330 * 5331 * Params: 5332 * x = X position to place first glyph 5333 * y = Y position to place first glyph 5334 */ 5335 Glyph[] textToGlyphs(double x, double y, string text, Glyph[] glyphBuffer = []) 5336 { 5337 Glyph* gPtr = null; 5338 int gLen = 0; 5339 if(glyphBuffer.length != 0) 5340 { 5341 gPtr = glyphBuffer.ptr; 5342 gLen = glyphBuffer.length.toCairoCount(); 5343 } 5344 5345 throwError(cairo_scaled_font_text_to_glyphs(this.nativePointer, x, y, 5346 text.ptr, text.length.toCairoCount(), &gPtr, &gLen, null, null, null)); 5347 5348 if(gPtr == glyphBuffer.ptr) 5349 { 5350 return glyphBuffer[0 .. gLen]; 5351 } 5352 else 5353 { 5354 Glyph[] gCopy = gPtr[0 .. gLen].dup; 5355 cairo_glyph_free(gPtr); 5356 return gCopy; 5357 } 5358 } 5359 ///ditto 5360 Glyph[] textToGlyphs(Point!double p1, string text, Glyph[] glyphBuffer = []) 5361 { 5362 return textToGlyphs(p1.x, p1.y, text, glyphBuffer); 5363 } 5364 ///ditto 5365 TextGlyph textToTextGlyph(double x, double y, string text, Glyph[] glyphBuffer = [], 5366 TextCluster[] clusterBuffer = []) 5367 { 5368 TextGlyph res; 5369 5370 Glyph* gPtr = null; 5371 int gLen = 0; 5372 TextCluster* cPtr = null; 5373 int cLen = 0; 5374 TextClusterFlags cFlags; 5375 if(glyphBuffer.length != 0) 5376 { 5377 gPtr = glyphBuffer.ptr; 5378 gLen = glyphBuffer.length.toCairoCount(); 5379 } 5380 if(clusterBuffer.length != 0) 5381 { 5382 cPtr = clusterBuffer.ptr; 5383 cLen = clusterBuffer.length.toCairoCount(); 5384 } 5385 5386 throwError(cairo_scaled_font_text_to_glyphs(this.nativePointer, x, y, 5387 text.ptr, text.length.toCairoCount(), &gPtr, &gLen, &cPtr, &cLen, &cFlags)); 5388 5389 if(gPtr == glyphBuffer.ptr) 5390 { 5391 res.glyphs = glyphBuffer[0 .. gLen]; 5392 } 5393 else 5394 { 5395 res.glyphs = gPtr[0 .. gLen].dup; 5396 cairo_glyph_free(gPtr); 5397 } 5398 if(cPtr == clusterBuffer.ptr) 5399 { 5400 res.cluster = clusterBuffer[0 .. cLen]; 5401 } 5402 else 5403 { 5404 res.cluster = cPtr[0 .. cLen].dup; 5405 cairo_text_cluster_free(cPtr); 5406 } 5407 5408 res.text = text; 5409 res.flags = cFlags; 5410 return res; 5411 } 5412 ///ditto 5413 TextGlyph textToTextGlyph(Point!double p1, string text, Glyph[] glyphBuffer = [], 5414 TextCluster[] clusterBuffer = []) 5415 { 5416 return textToTextGlyph(p1.x, p1.y, text, glyphBuffer, clusterBuffer); 5417 } 5418 5419 /** 5420 * Gets the font face that this scaled font uses. This is the 5421 * font face passed to $(D new ScaledFont()). 5422 */ 5423 FontFace getFontFace() 5424 { 5425 auto face = cairo_scaled_font_get_font_face(this.nativePointer); 5426 checkError(); 5427 return FontFace.createFromNative(face); 5428 } 5429 5430 ///convenience alias 5431 alias getFontFace fontFace; 5432 5433 /** 5434 * Returns the font options with which ScaledFont 5435 * was created. 5436 */ 5437 FontOptions getFontOptions() 5438 { 5439 //TODO: verify if this is correct 5440 FontOptions fo = FontOptions.create(); 5441 cairo_scaled_font_get_font_options(this.nativePointer, fo.nativePointer); 5442 checkError(); 5443 return fo; 5444 } 5445 5446 ///convenience alias 5447 alias getFontOptions fontOptions; 5448 5449 /** 5450 * Returns the font matrix with which ScaledFont 5451 * was created. 5452 */ 5453 Matrix getFontMatrix() 5454 { 5455 Matrix mat; 5456 cairo_scaled_font_get_font_matrix(this.nativePointer, &mat.nativeMatrix); 5457 checkError(); 5458 return mat; 5459 } 5460 5461 ///convenience alias 5462 alias getFontMatrix fontMatrix; 5463 5464 /** 5465 * Returns the CTM with which ScaledFont was created. 5466 * Note that the translation offsets (x0, y0) of the CTM are 5467 * ignored by $(D new ScaledFont()). So, the matrix this function 5468 * returns always has 0,0 as x0,y0. 5469 */ 5470 Matrix getCTM() 5471 { 5472 Matrix mat; 5473 cairo_scaled_font_get_ctm(this.nativePointer, &mat.nativeMatrix); 5474 checkError(); 5475 return mat; 5476 } 5477 5478 ///convenience alias 5479 alias getCTM CTM; 5480 5481 /** 5482 * Returns the scale matrix of ScaledFont. 5483 * The scale matrix is product of the font matrix and the 5484 * ctm associated with the scaled font, and hence is the 5485 * matrix mapping from font space to device space. 5486 */ 5487 Matrix getScaleMatrix() 5488 { 5489 Matrix mat; 5490 cairo_scaled_font_get_scale_matrix(this.nativePointer, &mat.nativeMatrix); 5491 checkError(); 5492 return mat; 5493 } 5494 5495 ///convenience alias 5496 alias getScaleMatrix scaleMatrix; 5497 5498 /** 5499 * This function returns the C type of a ScaledFont. See $(D FontType) 5500 * for available types. 5501 */ 5502 FontType getType() 5503 { 5504 auto tmp = cairo_scaled_font_get_type(this.nativePointer); 5505 checkError(); 5506 return tmp; 5507 } 5508 5509 ///convenience alias 5510 alias getType type; 5511 } 5512 5513 /** 5514 * Base class for font faces 5515 * 5516 * $(D FontFace) represents a particular font at a particular weight, 5517 * slant, and other characteristic but no size, transformation, or size. 5518 * 5519 * Font faces are created using font-backend-specific classes, 5520 * typically of the form $(D *FontFace), or implicitly 5521 * using the toy text API by way of $(D Context.selectFontFace()). The 5522 * resulting face can be accessed using $(D Context.getFontFace()). 5523 */ 5524 public class FontFace 5525 { 5526 /// 5527 mixin CairoCountedClass!(cairo_font_face_t*, "cairo_font_face_"); 5528 5529 protected: 5530 /** 5531 * Method for use in subclasses. 5532 * Calls $(D cairo_font_face_status(nativePointer)) and throws 5533 * an exception if the status isn't CAIRO_STATUS_SUCCESS 5534 */ 5535 final void checkError() 5536 { 5537 throwError(cairo_font_face_status(nativePointer)); 5538 } 5539 5540 public: 5541 /** 5542 * Create a $(D FontFace) from a existing $(D cairo_font_face_t*). 5543 * FontFace is a garbage collected class. It will call $(D cairo_font_face_destroy) 5544 * when it gets collected by the GC or when $(D dispose()) is called. 5545 * 5546 * Warning: 5547 * $(D ptr)'s reference count is not increased by this function! 5548 * Adjust reference count before calling it if necessary 5549 * 5550 * $(RED Only use this if you know what your doing! 5551 * This function should not be needed for standard cairoD usage.) 5552 */ 5553 this(cairo_font_face_t* ptr) 5554 { 5555 this.nativePointer = ptr; 5556 checkError(); 5557 } 5558 5559 /** 5560 * The createFromNative method for the FontFace classes. 5561 * See $(LINK https://github.com/jpf91/cairoD/wiki/Memory-Management#createFromNative) 5562 * for more information. 5563 * 5564 * Warning: 5565 * $(RED Only use this if you know what your doing! 5566 * This function should not be needed for standard cairoD usage.) 5567 */ 5568 static FontFace createFromNative(cairo_font_face_t* ptr, bool adjRefCount = true) 5569 { 5570 if(!ptr) 5571 { 5572 throw new CairoException(cairo_status_t.CAIRO_STATUS_NULL_POINTER); 5573 } 5574 throwError(cairo_font_face_status(ptr)); 5575 //Adjust reference count 5576 if(adjRefCount) 5577 cairo_font_face_reference(ptr); 5578 switch(cairo_font_face_get_type(ptr)) 5579 { 5580 case cairo_font_type_t.CAIRO_FONT_TYPE_TOY: 5581 return new ToyFontFace(ptr); 5582 static if(CAIRO_HAS_WIN32_FONT) 5583 { 5584 import cairo.win32; 5585 case cairo_font_type_t.CAIRO_FONT_TYPE_WIN32: 5586 return new Win32FontFace(ptr); 5587 } 5588 static if(CAIRO_HAS_FT_FONT) 5589 { 5590 import cairo.ft; 5591 case cairo_font_type_t.CAIRO_FONT_TYPE_FT: 5592 return new FTFontFace(ptr); 5593 } 5594 default: 5595 return new FontFace(ptr); 5596 } 5597 } 5598 5599 /** 5600 * This function returns the C type of a FontFace. See $(D FontType) 5601 * for available types. 5602 */ 5603 FontType getType() 5604 { 5605 auto tmp = cairo_font_face_get_type(this.nativePointer); 5606 checkError(); 5607 return tmp; 5608 } 5609 5610 ///convenience alias 5611 alias getType type; 5612 } 5613 5614 /** 5615 * Cairo toy font api's FontFace 5616 */ 5617 public class ToyFontFace : FontFace 5618 { 5619 public: 5620 /** 5621 * Create a $(D ToyFontFace) from a existing $(D cairo_font_face_t*). 5622 * ToyFontFace is a garbage collected class. It will call $(D cairo_surface_destroy) 5623 * when it gets collected by the GC or when $(D dispose()) is called. 5624 * 5625 * Warning: 5626 * $(D ptr)'s reference count is not increased by this function! 5627 * Adjust reference count before calling it if necessary 5628 * 5629 * $(RED Only use this if you know what your doing! 5630 * This function should not be needed for standard cairoD usage.) 5631 */ 5632 this(cairo_font_face_t* ptr) 5633 { 5634 super(ptr); 5635 } 5636 5637 /** 5638 * Creates a font face from a triplet of family, slant, and weight. 5639 * These font faces are used in implementation of the the cairo "toy" font API. 5640 * 5641 * If family is the zero-length string "", the platform-specific 5642 * default family is assumed. The default family then 5643 * can be queried using $(D getFamily()). 5644 * 5645 * The $(D Context.selectFontFace()) function uses this to create 5646 * font faces. See that function for limitations and 5647 * other details of toy font faces. 5648 */ 5649 this(string family, FontSlant slant, FontWeight weight) 5650 { 5651 super(cairo_toy_font_face_create(toStringz(family), slant, weight)); 5652 } 5653 5654 /** 5655 * Gets the familly name of a toy font. 5656 */ 5657 string getFamily() 5658 { 5659 auto ptr = cairo_toy_font_face_get_family(this.nativePointer); 5660 checkError(); 5661 return to!string(ptr); 5662 } 5663 5664 ///convenience alias 5665 alias getFamily family; 5666 5667 /** 5668 * Gets the slant a toy font. 5669 */ 5670 FontSlant getSlant() 5671 { 5672 auto res = cairo_toy_font_face_get_slant(this.nativePointer); 5673 checkError(); 5674 return res; 5675 } 5676 5677 ///convenience alias 5678 alias getSlant slant; 5679 5680 /** 5681 * Gets the weight of a toy font. 5682 */ 5683 FontWeight getWeight() 5684 { 5685 auto res = cairo_toy_font_face_get_weight(this.nativePointer); 5686 checkError(); 5687 return res; 5688 } 5689 5690 ///convenience alias 5691 alias getWeight weight; 5692 } 5693 5694 /** 5695 * Cairo version information 5696 */ 5697 public struct Version 5698 { 5699 public: 5700 ///Major, Minor and Micro versions 5701 uint major; 5702 uint minor; ///ditto 5703 uint micro; ///ditto 5704 5705 /** 5706 * Construct a version object from a encoded version. 5707 */ 5708 this(ulong encoded) 5709 { 5710 this.major = cast(uint)(encoded / 10000); 5711 this.minor = cast(uint)((encoded % 10000) / 100); 5712 this.micro = cast(uint)((encoded % 10000) % 100); 5713 } 5714 5715 /** 5716 * Construct a version object from version components. 5717 */ 5718 this(uint major, uint minor, uint micro) 5719 { 5720 this.major = major; 5721 this.minor = minor; 5722 this.micro = micro; 5723 } 5724 5725 /** 5726 * Return the (runtime) version of the used cairo 5727 * library. 5728 */ 5729 static @property Version cairoVersion() 5730 { 5731 return Version(cairo_version()); 5732 } 5733 5734 /** 5735 * Returns the (compile time) version of this binding / wrapper. 5736 */ 5737 static @property Version bindingVersion() 5738 { 5739 return Version(CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR, 5740 CAIRO_VERSION_MICRO); 5741 } 5742 5743 /** 5744 * Returns the version in encoded form. 5745 */ 5746 ulong encode() 5747 { 5748 return CAIRO_VERSION_ENCODE(major, minor, micro); 5749 } 5750 5751 /** 5752 * toString implementation 5753 */ 5754 string toString() 5755 { 5756 return CAIRO_VERSION_STRINGIZE(major, minor, micro); 5757 } 5758 } 5759 5760 5761 /** 5762 * RandomAccessRange to iterate or index into Clips of a Cairo Region. 5763 * This range keeps a reference to its $(D Region) object, 5764 * so it can be passed around without thinking about memory management. 5765 */ 5766 public struct ClipRange 5767 { 5768 private Region _outer; 5769 private int _a, _b; 5770 5771 this(Region data) 5772 { 5773 _outer = data; 5774 _b = _outer.numRectangles(); 5775 } 5776 5777 this(Region data, int a, int b) 5778 { 5779 _outer = data; 5780 _a = a; 5781 _b = b; 5782 } 5783 5784 @property bool empty() // const 5785 { 5786 assert(_outer.numRectangles() >= _b); 5787 return _a >= _b; 5788 } 5789 5790 @property typeof(this) save() 5791 { 5792 return this; 5793 } 5794 5795 @property Rectangle!int front() 5796 { 5797 assert(!empty); 5798 return _outer.getRectangle(_a); 5799 } 5800 5801 @property Rectangle!int back() 5802 { 5803 assert(!empty); 5804 return _outer.getRectangle(_b - 1); 5805 } 5806 5807 void popFront() 5808 { 5809 assert(!empty); 5810 ++_a; 5811 } 5812 5813 void popBack() 5814 { 5815 assert(!empty); 5816 --_b; 5817 } 5818 5819 Rectangle!int opIndex(int i) 5820 { 5821 i += _a; 5822 assert(i < _b && _b <= _outer.numRectangles); 5823 return _outer.getRectangle(i); 5824 } 5825 5826 typeof(this) opSlice() 5827 { 5828 return this; 5829 } 5830 5831 typeof(this) opSlice(int a, int b) 5832 { 5833 return typeof(this)(_outer, a + _a, b + _a); 5834 } 5835 5836 @property size_t length() const { 5837 return _b - _a; 5838 } 5839 } 5840 5841 unittest 5842 { 5843 import std.range; 5844 static assert(isRandomAccessRange!ClipRange); 5845 } 5846 5847 unittest 5848 { 5849 import std.array, std.range; 5850 auto rect1 = Rectangle!int(0, 0, 100, 100); 5851 auto rect2 = Rectangle!int(200, 200, 100, 100); 5852 5853 static assert(!hasLvalueElements!ClipRange); 5854 5855 auto region = Region(rect1); 5856 region.unionWith(rect2); 5857 5858 assert(region.getRectangles().length == 2); 5859 assert(region.getRectangles()[].length == 2); 5860 assert(array(region.getRectangles()) == [rect1, rect2]); 5861 5862 assert(region.getRectangles()[1..2].length == 1); 5863 assert(region.getRectangles()[1..2][0] == rect2); 5864 5865 assert(region.getRectangles()[0] == rect1); 5866 assert(region.getRectangles()[1] == rect2); 5867 5868 foreach (int i, clip; [rect1, rect2]) 5869 { 5870 assert(region.getRectangles()[i] == clip); 5871 } 5872 5873 /* @BUG@ Access Violation */ 5874 //foreach (regRect, oldRect; lockstep(region.getRectangles(), region.getRectangles())) 5875 auto oldRects = [rect1, rect2]; 5876 size_t i = 0; 5877 foreach (Rectangle!int regRect; region.getRectangles()) 5878 { 5879 assert(regRect == oldRects[i++]); 5880 } 5881 } 5882 5883 5884 public struct Region 5885 { 5886 /*---------------------------Reference counting stuff---------------------------*/ 5887 protected: 5888 void _reference() 5889 { 5890 cairo_region_reference(this.nativePointer); 5891 } 5892 5893 void _dereference() 5894 { 5895 cairo_region_destroy(this.nativePointer); 5896 } 5897 5898 public: 5899 /** 5900 * The underlying $(D cairo_t*) handle 5901 */ 5902 cairo_region_t* nativePointer; 5903 version(D_Ddoc) 5904 { 5905 /** 5906 * Enable / disable memory management debugging for this Context 5907 * instance. Only available if both cairoD and the cairoD user 5908 * code were compiled with "debug=RefCounted" 5909 * 5910 * Output is written to stdout, see 5911 * $(LINK https://github.com/jpf91/cairoD/wiki/Memory-Management#debugging) 5912 * for more information 5913 */ 5914 bool debugging = false; 5915 } 5916 else debug(RefCounted) 5917 { 5918 bool debugging = false; 5919 } 5920 5921 /** 5922 * Constructor that tracks the reference count appropriately. If $(D 5923 * !refCountedIsInitialized), does nothing. 5924 */ 5925 this(this) 5926 { 5927 if (this.nativePointer is null) 5928 return; 5929 this._reference(); 5930 debug(RefCounted) 5931 if (this.debugging) 5932 { 5933 writeln(typeof(this).stringof, 5934 "@", cast(void*) this.nativePointer, ": bumped refcount."); 5935 } 5936 } 5937 5938 ~this() 5939 { 5940 this.dispose(); 5941 } 5942 5943 /** 5944 * Explicitly drecrease the reference count. 5945 * 5946 * See $(LINK https://github.com/jpf91/cairoD/wiki/Memory-Management#2.1-structs) 5947 * for more information. 5948 */ 5949 void dispose() 5950 { 5951 if (this.nativePointer is null) 5952 return; 5953 5954 debug(RefCounted) 5955 if (this.debugging) 5956 { 5957 writeln(typeof(this).stringof, 5958 "@", cast(void*)this.nativePointer, 5959 ": decrement refcount"); 5960 } 5961 this._dereference(); 5962 this.nativePointer = null; 5963 } 5964 5965 /** 5966 * Assignment operator 5967 */ 5968 void opAssign(Region rhs) 5969 { 5970 this.nativePointer = cairo_region_copy(rhs.nativePointer); 5971 debug(RefCounted) 5972 this.debugging = rhs.debugging; 5973 } 5974 /*------------------------End of Reference counting-----------------------*/ 5975 5976 public: 5977 this(Region region) 5978 { 5979 this(cairo_region_copy(region.nativePointer)); 5980 debug(RefCounted) 5981 this.debugging = region.debugging; 5982 } 5983 5984 /** 5985 * Create a $(D Region) from a existing $(D cairo_region_t*). 5986 * Context is a garbage collected class. It will call $(D cairo_region_destroy) 5987 * when it gets collected by the GC or when $(D dispose()) is called. 5988 * 5989 * Warning: 5990 * $(D ptr)'s reference count is not increased by this function! 5991 * Adjust reference count before calling it if necessary 5992 * 5993 * $(RED Only use this if you know what your doing! 5994 * This function should not be needed for standard cairoD usage.) 5995 */ 5996 this(cairo_region_t* ptr) 5997 { 5998 this.nativePointer = ptr; 5999 if(!ptr) 6000 { 6001 throw new CairoException(cairo_status_t.CAIRO_STATUS_NULL_POINTER); 6002 } 6003 checkError(); 6004 } 6005 6006 protected: 6007 /** 6008 * Method for use in subclasses. 6009 * Calls $(D cairo_region_status(nativePointer)) and throws 6010 * an exception if the status isn't CAIRO_STATUS_SUCCESS 6011 */ 6012 final void checkError() 6013 { 6014 throwError(cairo_region_status(nativePointer)); 6015 } 6016 6017 public: 6018 /** 6019 * Create a new, empty region 6020 * 6021 * Note: The Region constructors can be used to create a new Region with Rectangles 6022 */ 6023 static Region create() 6024 { 6025 return Region(cairo_region_create()); 6026 } 6027 6028 /** 6029 * 6030 */ 6031 Region copy() 6032 { 6033 return Region(cairo_region_copy(this.nativePointer)); 6034 } 6035 6036 /** 6037 * 6038 */ 6039 this(Rectangle!int rect) 6040 { 6041 this(cairo_region_create_rectangle(cast(cairo_rectangle_int_t*)&rect)); 6042 } 6043 6044 /** 6045 * 6046 */ 6047 this(Rectangle!int[] rects) 6048 { 6049 this(cairo_region_create_rectangles(cast(cairo_rectangle_int_t*)rects.ptr, rects.length.toCairoCount())); 6050 } 6051 6052 /** 6053 * 6054 */ 6055 Rectangle!int getExtents() 6056 { 6057 Rectangle!int extents; 6058 cairo_region_get_extents(this.nativePointer, cast(cairo_rectangle_int_t*)&extents); 6059 checkError(); 6060 return extents; 6061 } 6062 6063 /** 6064 * 6065 */ 6066 int numRectangles() 6067 { 6068 return cairo_region_num_rectangles(this.nativePointer); 6069 } 6070 6071 /** 6072 * 6073 */ 6074 Rectangle!int getRectangle(int index) 6075 { 6076 Rectangle!int rect; 6077 cairo_region_get_rectangle(this.nativePointer, index, cast(cairo_rectangle_int_t*)&rect); 6078 checkError(); 6079 return rect; 6080 } 6081 6082 /** 6083 * 6084 */ 6085 auto getRectangles() 6086 { 6087 return ClipRange(this); 6088 } 6089 6090 /** 6091 * 6092 */ 6093 bool isEmpty() 6094 { 6095 return cast(bool)cairo_region_is_empty(this.nativePointer); 6096 } 6097 6098 /** 6099 * 6100 */ 6101 RegionOverlap containsRectangle(Rectangle!int rect) 6102 { 6103 return cairo_region_contains_rectangle(this.nativePointer, cast(cairo_rectangle_int_t*)&rect); 6104 } 6105 6106 /** 6107 * 6108 */ 6109 bool containsPoint(Point!int point) 6110 { 6111 return cast(bool)cairo_region_contains_point(this.nativePointer, point.x, point.y); 6112 } 6113 6114 /** 6115 * 6116 */ 6117 const bool opEquals(ref const(Region) other) 6118 { 6119 return cast(bool)cairo_region_equal(this.nativePointer, other.nativePointer); 6120 } 6121 6122 /** 6123 * 6124 */ 6125 void translate(int dx, int dy) 6126 { 6127 cairo_region_translate(this.nativePointer, dx, dy); 6128 checkError(); 6129 } 6130 6131 /** 6132 * 6133 */ 6134 void intersect(Region other) 6135 { 6136 throwError(cairo_region_intersect(this.nativePointer, other.nativePointer)); 6137 } 6138 /** 6139 * 6140 */ 6141 void intersect(Rectangle!int other) 6142 { 6143 throwError(cairo_region_intersect_rectangle(this.nativePointer, cast(cairo_rectangle_int_t*)&other)); 6144 } 6145 6146 /** 6147 * 6148 */ 6149 void subtract(Region other) 6150 { 6151 throwError(cairo_region_subtract_rectangle(this.nativePointer, cast(cairo_rectangle_int_t*)&other)); 6152 } 6153 6154 /** 6155 * 6156 */ 6157 void subtract(Rectangle!int other) 6158 { 6159 throwError(cairo_region_subtract_rectangle(this.nativePointer, cast(cairo_rectangle_int_t*)&other)); 6160 } 6161 6162 /** 6163 * 6164 */ 6165 void unionWith(Region other) 6166 { 6167 throwError(cairo_region_union(this.nativePointer, other.nativePointer)); 6168 } 6169 6170 /** 6171 * 6172 */ 6173 void unionWith(Rectangle!int other) 6174 { 6175 throwError(cairo_region_union_rectangle(this.nativePointer, cast(cairo_rectangle_int_t*)&other)); 6176 } 6177 6178 /** 6179 * 6180 */ 6181 void xor(Region other) 6182 { 6183 throwError(cairo_region_xor(this.nativePointer, other.nativePointer)); 6184 } 6185 6186 /** 6187 * 6188 */ 6189 void xor(Rectangle!int other) 6190 { 6191 throwError(cairo_region_xor_rectangle(this.nativePointer, cast(cairo_rectangle_int_t*)&other)); 6192 } 6193 } 6194 6195 unittest 6196 { 6197 auto rect1 = Rectangle!int(0, 0, 100, 100); 6198 auto region = Region(rect1); 6199 6200 assert(region.numRectangles == 1); 6201 assert(!region.isEmpty()); 6202 6203 assert(region.containsPoint(Point!int(50, 0))); 6204 assert(!region.containsPoint(Point!int(100, 0))); // 100 is over the range of 0 .. 100 (99 is max) 6205 6206 region.translate(10, 0); 6207 assert(region.containsPoint(Point!int(100, 0))); // range is now 10 .. 110 6208 assert(!region.containsPoint(Point!int(0, 0))); // 0 is below the minimum of 10 6209 6210 region.xor(region); // xor, 1 ^ 1 == 0 :) 6211 assert(region.isEmpty()); 6212 6213 auto rect2 = Rectangle!int(99, 0, 100, 100); 6214 region = Region([rect1, rect2]); 6215 assert(region.numRectangles == 1); // note: cairo merges the two rectangles as they 6216 // form a closed rectangle path. 6217 6218 rect2.point.x = 120; 6219 region = Region([rect1, rect2]); 6220 assert(region.numRectangles == 2); // now they can't be merged 6221 6222 region = Region(rect1); 6223 region.unionWith(rect2); 6224 assert(region.numRectangles == 2); // same thing when using a union 6225 6226 rect2.point.x += 10; 6227 region.subtract(rect2); 6228 assert(region.numRectangles == 2); // still two rectangles due to extra edge 6229 6230 rect2.point.x -= 10; 6231 region.subtract(rect2); 6232 assert(region.numRectangles == 1); // and now the second rectangle is completely gone 6233 6234 region.subtract(rect1); 6235 assert(region.isEmpty); // first rectangle also gone, region is empty 6236 6237 auto region1 = Region(rect1); 6238 auto region2 = Region(rect1); 6239 assert(region1 == region2); 6240 } 6241 6242 unittest 6243 { 6244 auto surface = new ImageSurface(Format.CAIRO_FORMAT_ARGB32, 100, 100); 6245 auto ctx = Context(surface); 6246 6247 ctx.rectangle(10, 20, 100, 100); 6248 auto path = ctx.copyPath(); 6249 6250 size_t index; 6251 foreach (element; path[]) 6252 { 6253 switch (element.type) 6254 { 6255 case PathElementType.CAIRO_PATH_MOVE_TO: 6256 { 6257 assert(element[0].x == 10 && element[0].y == 20); 6258 break; 6259 } 6260 case PathElementType.CAIRO_PATH_LINE_TO: 6261 { 6262 if (index == 1) 6263 assert(element[0].x == 110 && element[0].y == 20); 6264 else if (index == 2) 6265 assert(element[0].x == 110 && element[0].y == 120); 6266 else if (index == 3) 6267 assert(element[0].x == 10 && element[0].y == 120); 6268 break; 6269 } 6270 default: 6271 } 6272 index++; 6273 } 6274 }