| 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 |