OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011, Google Inc. | 2 * Copyright 2011, Google Inc. |
3 * All rights reserved. | 3 * All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
7 * met: | 7 * met: |
8 * | 8 * |
9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 } | 78 } |
79 | 79 |
80 void RendererCairo::Paint() { | 80 void RendererCairo::Paint() { |
81 // TODO(tschmelcher): Don't keep creating and destroying the drawing context. | 81 // TODO(tschmelcher): Don't keep creating and destroying the drawing context. |
82 cairo_t* current_drawing = cairo_create(main_surface_); | 82 cairo_t* current_drawing = cairo_create(main_surface_); |
83 | 83 |
84 // Redirect drawing to an off-screen surface (holding only colour information, | 84 // Redirect drawing to an off-screen surface (holding only colour information, |
85 // without an alpha channel). | 85 // without an alpha channel). |
86 cairo_push_group_with_content(current_drawing, CAIRO_CONTENT_COLOR); | 86 cairo_push_group_with_content(current_drawing, CAIRO_CONTENT_COLOR); |
87 | 87 |
| 88 // Set fill (and clip) rule. |
| 89 cairo_set_fill_rule(current_drawing, CAIRO_FILL_RULE_EVEN_ODD); |
| 90 |
88 // Sort layers by z value. | 91 // Sort layers by z value. |
89 // TODO(tschmelcher): Only sort when changes are made. | 92 // TODO(tschmelcher): Only sort when changes are made. |
90 layer_list_.sort(LayerZValueLessThan); | 93 layer_list_.sort(LayerZValueLessThan); |
91 | 94 |
92 // Paint the background. | 95 // Paint the background. |
93 PaintBackground(current_drawing); | 96 PaintBackground(current_drawing); |
94 | 97 |
95 // Core process of painting. | 98 // Core process of painting. |
96 for (LayerList::iterator i = layer_list_.begin(); | 99 for (LayerList::iterator i = layer_list_.begin(); |
97 i != layer_list_.end(); i++) { | 100 i != layer_list_.end(); i++) { |
98 Layer* cur = *i; | 101 Layer* cur = *i; |
99 if (!cur->ShouldPaint()) continue; | 102 if (!cur->ShouldPaint()) continue; |
100 | 103 |
101 Pattern* pattern = cur->pattern(); | 104 Pattern* pattern = cur->pattern(); |
102 | 105 |
103 // Save the current drawing state. | 106 // Save the current drawing state. |
104 cairo_save(current_drawing); | 107 cairo_save(current_drawing); |
105 | 108 |
106 // Clip areas that will be obscured anyway. | 109 // Clip the region outside the current Layer. |
107 LayerList::iterator start_mask_it = i; | |
108 start_mask_it++; | |
109 ClipArea(current_drawing, start_mask_it); | |
110 | |
111 // Define the region to fill. | |
112 cairo_rectangle(current_drawing, | 110 cairo_rectangle(current_drawing, |
113 cur->x(), | 111 cur->x(), |
114 cur->y(), | 112 cur->y(), |
115 cur->width(), | 113 cur->width(), |
116 cur->height()); | 114 cur->height()); |
| 115 cairo_clip(current_drawing); |
117 | 116 |
118 // Transform the pattern to fit into the fill region. | 117 // Clip the regions within other Layers that will obscure this one. |
| 118 LayerList::iterator start_mask_it = i; |
| 119 start_mask_it++; |
| 120 ClipArea(current_drawing, start_mask_it); |
| 121 |
| 122 // Transform the pattern to fit into the Layer's region. |
119 cairo_translate(current_drawing, cur->x(), cur->y()); | 123 cairo_translate(current_drawing, cur->x(), cur->y()); |
120 cairo_scale(current_drawing, cur->scale_x(), cur->scale_y()); | 124 cairo_scale(current_drawing, cur->scale_x(), cur->scale_y()); |
121 | 125 |
122 // Set source pattern. | 126 // Set source pattern. |
123 cairo_set_source(current_drawing, pattern->pattern()); | 127 cairo_set_source(current_drawing, pattern->pattern()); |
124 | 128 |
125 // Paint the pattern to the off-screen surface. | 129 // Paint the pattern to the off-screen surface. |
126 switch (cur->paint_operator()) { | 130 switch (cur->paint_operator()) { |
127 case Layer::BLEND: | 131 case Layer::BLEND: |
128 cairo_fill(current_drawing); | 132 cairo_paint(current_drawing); |
129 break; | 133 break; |
130 | 134 |
131 case Layer::BLEND_WITH_TRANSPARENCY: | 135 case Layer::BLEND_WITH_TRANSPARENCY: |
132 { | 136 cairo_paint_with_alpha(current_drawing, cur->alpha()); |
133 cairo_pattern_t* mask = cairo_pattern_create_rgba(0.0, | |
134 0.0, | |
135 0.0, | |
136 cur->alpha()); | |
137 cairo_mask(current_drawing, mask); | |
138 cairo_pattern_destroy(mask); | |
139 } | |
140 break; | 137 break; |
141 | 138 |
142 // TODO(tschmelcher): COPY_WITH_FADING is not implemented yet. For now | |
143 // we treat it the same as COPY. | |
144 case Layer::COPY_WITH_FADING: | |
145 case Layer::COPY: | 139 case Layer::COPY: |
146 // Set Cairo to copy the pattern's alpha content instead of blending. | 140 // Set Cairo to copy the pattern's alpha content instead of blending. |
147 cairo_set_operator(current_drawing, CAIRO_OPERATOR_SOURCE); | 141 cairo_set_operator(current_drawing, CAIRO_OPERATOR_SOURCE); |
148 cairo_fill(current_drawing); | 142 cairo_paint(current_drawing); |
| 143 break; |
| 144 |
| 145 case Layer::COPY_WITH_FADING: |
| 146 // TODO(tschmelcher): This can also be done in a single operation with: |
| 147 // |
| 148 // cairo_set_operator(current_drawing, CAIRO_OPERATOR_IN); |
| 149 // cairo_paint_with_alpha(current_drawing, cur->alpha()); |
| 150 // |
| 151 // but surprisingly that is slightly slower for me. We should figure out |
| 152 // why. |
| 153 cairo_set_operator(current_drawing, CAIRO_OPERATOR_CLEAR); |
| 154 cairo_paint(current_drawing); |
| 155 cairo_set_operator(current_drawing, CAIRO_OPERATOR_OVER); |
| 156 cairo_paint_with_alpha(current_drawing, cur->alpha()); |
149 break; | 157 break; |
150 | 158 |
151 default: | 159 default: |
152 DCHECK(false); | 160 DCHECK(false); |
153 } | 161 } |
154 | 162 |
155 // Restore to a clean state. | 163 // Restore to a clean state. |
156 cairo_restore(current_drawing); | 164 cairo_restore(current_drawing); |
157 } | 165 } |
158 | 166 |
(...skipping 11 matching lines...) Expand all Loading... |
170 cairo_save(cr); | 178 cairo_save(cr); |
171 ClipArea(cr, layer_list_.begin()); | 179 ClipArea(cr, layer_list_.begin()); |
172 | 180 |
173 cairo_rectangle(cr, 0, 0, display_width(), display_height()); | 181 cairo_rectangle(cr, 0, 0, display_width(), display_height()); |
174 cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); | 182 cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); |
175 cairo_fill(cr); | 183 cairo_fill(cr); |
176 cairo_restore(cr); | 184 cairo_restore(cr); |
177 } | 185 } |
178 | 186 |
179 void RendererCairo::ClipArea(cairo_t* cr, LayerList::iterator it) { | 187 void RendererCairo::ClipArea(cairo_t* cr, LayerList::iterator it) { |
180 cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD); | |
181 | |
182 for (LayerList::iterator i = it; i != layer_list_.end(); i++) { | 188 for (LayerList::iterator i = it; i != layer_list_.end(); i++) { |
183 // Preparing and updating the Layer. | 189 // Preparing and updating the Layer. |
184 Layer* cur = *i; | 190 Layer* cur = *i; |
185 if (!cur->ShouldClip()) continue; | 191 if (!cur->ShouldClip()) continue; |
186 | 192 |
187 cairo_rectangle(cr, 0, 0, display_width(), display_height()); | 193 cairo_rectangle(cr, 0, 0, display_width(), display_height()); |
188 cairo_rectangle(cr, | 194 cairo_rectangle(cr, |
189 cur->x(), | 195 cur->x(), |
190 cur->y(), | 196 cur->y(), |
191 cur->width(), | 197 cur->width(), |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 NOTIMPLEMENTED(); | 471 NOTIMPLEMENTED(); |
466 } | 472 } |
467 | 473 |
468 void RendererCairo::PopRenderStates() { | 474 void RendererCairo::PopRenderStates() { |
469 NOTIMPLEMENTED(); | 475 NOTIMPLEMENTED(); |
470 } | 476 } |
471 | 477 |
472 } // namespace o2d | 478 } // namespace o2d |
473 | 479 |
474 } // namespace o3d | 480 } // namespace o3d |
OLD | NEW |