1 /// `ResolutionOverride` forcefully changes the resolution a node is drawn in, overriding layout
2 /// hints. This is useful if Fluid's graphical output is transformed as a post-process step that
3 /// demands a specific output size. This is commonly the case with Raylib's `RenderTexture`,
4 /// or Parin's resolution lock.
5 ///
6 /// Note that scaling Fluid's output as a post-process step will reduce quality, likely making
7 /// text blurry. It remains useful for pixel art-style applications with bitmap fonts, but for
8 /// other usecases, check with the `CanvasIO` system provider if it supports scaling. For Raylib,
9 /// you can use `fluid.raylib.RaylibView.scale`.
10 module fluid.resolution_override;
11 
12 import optional;
13 
14 import fluid.node;
15 import fluid.utils;
16 import fluid.types;
17 import fluid.structs;
18 import fluid.hover_transform;
19 
20 import fluid.io.canvas;
21 
22 /// Node builder for `ResolutionOverride`. It is a template, accepting the base node type
23 /// (like `resolutionOverride!Frame`) or another node builder (for example
24 /// `resolutionOverride!hframe`).
25 alias resolutionOverride(alias base) = nodeBuilder!(ResolutionOverride, base);
26 
27 /// This node sets a static resolution for its content, ignoring (overriding) whatever layout
28 /// was assigned by its parent.
29 ///
30 /// Works only with the new I/O system introduced in Fluid 0.7.2.
31 ///
32 /// `ResolutionOverride` requires an active instance of `CanvasIO` to work. It will locally
33 /// override its `dpi` value — with a default of `(96, 96)` —  to make sure the output
34 /// is consistent. The DPI value can be changed using the `dpi` method.
35 class ResolutionOverride(T : Node) : T, CanvasIO {
36 
37     CanvasIO canvasIO;
38 
39     public {
40 
41         /// Desired resolution for the lock. Specified in dots, rather than Fluid's
42         /// DPI-independent pixels, so it will not be affected by the scaling setting
43         /// of the desktop environment.
44         Vector2 resolution;
45 
46     }
47 
48     private {
49         auto _dpi = Vector2(96, 96);
50     }
51 
52     /// Create a node locked to a set resolution.
53     /// Params:
54     ///     resolution = Resolution to use, in dots.
55     ///     args       = Arguments to pass to the base node.
56     this(Ts...)(Vector2 resolution, Ts args) @safe {
57         super(args);
58         this.resolution = resolution;
59     }
60 
61     override void resizeImpl(Vector2) @safe {
62         require(canvasIO);
63 
64         auto io = this.implementIO();
65 
66         const size = canvasIO.fromDots(resolution);
67         super.resizeImpl(size);
68         minSize = size;
69     }
70 
71     override Rectangle marginBoxForSpace(Rectangle space) const {
72         const size = canvasIO.fromDots(resolution);
73         const position = layout.nodeAlign.alignRectangle(space, size);
74         return Rectangle(position.tupleof, size.tupleof);
75     }
76 
77     override Vector2 dpi() const nothrow {
78         return _dpi;
79     }
80 
81     Vector2 dpi(Vector2 value) nothrow {
82         return _dpi = value;
83     }
84 
85     // CanvasIO overrides
86 
87     override Optional!Rectangle cropArea() const nothrow {
88         return canvasIO.cropArea();
89     }
90 
91     override void cropArea(Rectangle area) nothrow {
92         canvasIO.cropArea(area);
93     }
94 
95     override void resetCropArea() nothrow {
96         canvasIO.resetCropArea();
97     }
98 
99     override void drawTriangleImpl(Vector2 a, Vector2 b, Vector2 c, Color color) nothrow {
100         canvasIO.drawTriangleImpl(a, b, c, color);
101     }
102 
103     override void drawCircleImpl(Vector2 center, float radius, Color color) nothrow {
104         canvasIO.drawCircleImpl(center, radius, color);
105     }
106 
107     override void drawCircleOutlineImpl(Vector2 center, float radius, float width, Color color)
108     nothrow {
109         canvasIO.drawCircleOutlineImpl(center, radius, width, color);
110     }
111 
112     override void drawRectangleImpl(Rectangle rectangle, Color color) nothrow {
113         canvasIO.drawRectangleImpl(rectangle, color);
114     }
115 
116     override void drawLineImpl(Vector2 start, Vector2 end, float width, Color color) nothrow {
117         canvasIO.drawLineImpl(start, end, width, color);
118     }
119 
120     override int load(Image image) nothrow {
121         return canvasIO.load(image);
122     }
123 
124     override void drawImageImpl(DrawableImage image, Rectangle destination, Color tint) nothrow {
125         canvasIO.drawImageImpl(image, destination, tint);
126     }
127 
128     override void drawHintedImageImpl(DrawableImage image, Rectangle destination, Color tint)
129     nothrow {
130         canvasIO.drawHintedImageImpl(image, destination, tint);
131     }
132 
133 }