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 // 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 ... | |
fbarchard
2011/01/21 02:26:00
comment should not say 'me' or people will wonder
Tristan Schmelcher 2
2011/01/21 18:31:29
Done.
| |
152 cairo_set_operator(current_drawing, CAIRO_OPERATOR_CLEAR); | |
153 cairo_paint(current_drawing); | |
154 cairo_set_operator(current_drawing, CAIRO_OPERATOR_OVER); | |
155 cairo_paint_with_alpha(current_drawing, cur->alpha()); | |
149 break; | 156 break; |
150 | 157 |
151 default: | 158 default: |
152 DCHECK(false); | 159 DCHECK(false); |
153 } | 160 } |
154 | 161 |
155 // Restore to a clean state. | 162 // Restore to a clean state. |
156 cairo_restore(current_drawing); | 163 cairo_restore(current_drawing); |
157 } | 164 } |
158 | 165 |
(...skipping 11 matching lines...) Expand all Loading... | |
170 cairo_save(cr); | 177 cairo_save(cr); |
171 ClipArea(cr, layer_list_.begin()); | 178 ClipArea(cr, layer_list_.begin()); |
172 | 179 |
173 cairo_rectangle(cr, 0, 0, display_width(), display_height()); | 180 cairo_rectangle(cr, 0, 0, display_width(), display_height()); |
174 cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); | 181 cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); |
175 cairo_fill(cr); | 182 cairo_fill(cr); |
176 cairo_restore(cr); | 183 cairo_restore(cr); |
177 } | 184 } |
178 | 185 |
179 void RendererCairo::ClipArea(cairo_t* cr, LayerList::iterator it) { | 186 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++) { | 187 for (LayerList::iterator i = it; i != layer_list_.end(); i++) { |
183 // Preparing and updating the Layer. | 188 // Preparing and updating the Layer. |
184 Layer* cur = *i; | 189 Layer* cur = *i; |
185 if (!cur->ShouldClip()) continue; | 190 if (!cur->ShouldClip()) continue; |
186 | 191 |
187 cairo_rectangle(cr, 0, 0, display_width(), display_height()); | 192 cairo_rectangle(cr, 0, 0, display_width(), display_height()); |
188 cairo_rectangle(cr, | 193 cairo_rectangle(cr, |
189 cur->x(), | 194 cur->x(), |
190 cur->y(), | 195 cur->y(), |
191 cur->width(), | 196 cur->width(), |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
465 NOTIMPLEMENTED(); | 470 NOTIMPLEMENTED(); |
466 } | 471 } |
467 | 472 |
468 void RendererCairo::PopRenderStates() { | 473 void RendererCairo::PopRenderStates() { |
469 NOTIMPLEMENTED(); | 474 NOTIMPLEMENTED(); |
470 } | 475 } |
471 | 476 |
472 } // namespace o2d | 477 } // namespace o2d |
473 | 478 |
474 } // namespace o3d | 479 } // namespace o3d |
OLD | NEW |