1/*
2    Copyright (C) 2009-2012 Samsung Electronics
3    Copyright (C) 2009-2010 ProFUSION embedded systems
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public
7    License as published by the Free Software Foundation; either
8    version 2 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public License
16    along with this library; see the file COPYING.LIB.  If not, write to
17    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18    Boston, MA 02110-1301, USA.
19*/
20
21#include "config.h"
22
23#include "TiledBackingStore.h"
24#include "ewk_paint_context_private.h"
25#include "ewk_private.h"
26
27#if ENABLE(INSPECTOR)
28#include "InspectorController.h"
29#include "Page.h"
30#endif
31
32Ewk_Paint_Context* ewk_paint_context_new(cairo_t* cairo)
33{
34    EINA_SAFETY_ON_NULL_RETURN_VAL(cairo, 0);
35
36    Ewk_Paint_Context* context = new Ewk_Paint_Context;
37    context->graphicContext = adoptPtr(new WebCore::GraphicsContext(cairo));
38    context->cairo = adoptRef(cairo_reference(cairo));
39    context->image = 0;
40    context->pixels = 0;
41
42    return context;
43}
44
45Ewk_Paint_Context* ewk_paint_context_from_image_new(Evas_Object* image)
46{
47    EINA_SAFETY_ON_NULL_RETURN_VAL(image, 0);
48
49    Evas_Coord width, height;
50    uint8_t* pixels = static_cast<uint8_t*>(evas_object_image_data_get(image, true));
51    evas_object_image_size_get(image, &width, &height);
52
53    Ewk_Paint_Context* context = ewk_paint_context_from_image_data_new(pixels, width, height, EVAS_COLORSPACE_ARGB8888);
54    if (context) {
55        context->pixels = pixels;
56        context->image = image;
57    }
58
59    return context;
60}
61
62Ewk_Paint_Context* ewk_paint_context_from_image_data_new(uint8_t* pixels, int width, int height, int colorSpace)
63{
64    EINA_SAFETY_ON_NULL_RETURN_VAL(pixels, 0);
65
66    OwnPtr<Ewk_Paint_Context> context = adoptPtr(new Ewk_Paint_Context);
67    context->pixels = pixels;
68    context->image = 0;
69
70    cairo_format_t format;
71    int stride;
72    switch (colorSpace) {
73    case EVAS_COLORSPACE_ARGB8888:
74        stride = width * 4;
75        format = CAIRO_FORMAT_ARGB32;
76        break;
77    case EVAS_COLORSPACE_RGB565_A5P:
78        stride = width * 2;
79        format = CAIRO_FORMAT_RGB16_565;
80        break;
81    default:
82        ERR("unknown color space: %d", colorSpace);
83        return 0;
84    }
85
86    context->surface = adoptRef(cairo_image_surface_create_for_data(pixels, format, width, height, stride));
87    cairo_status_t status = cairo_surface_status(context->surface.get());
88    if (status != CAIRO_STATUS_SUCCESS) {
89        ERR("could not create surface from data %dx%d: %s", width, height, cairo_status_to_string(status));
90        return 0;
91    }
92
93    context->cairo = adoptRef(cairo_create(context->surface.get()));
94    status = cairo_status(context->cairo.get());
95    if (status != CAIRO_STATUS_SUCCESS) {
96        ERR("could not create cairo from surface %dx%d: %s", width, height, cairo_status_to_string(status));
97        return 0;
98    }
99
100    context->graphicContext = adoptPtr(new WebCore::GraphicsContext(context->cairo.get()));
101
102    return context.release().leakPtr();
103}
104
105void ewk_paint_context_free(Ewk_Paint_Context* context)
106{
107    EINA_SAFETY_ON_NULL_RETURN(context);
108
109    if (context->image && context->pixels) {
110        // Decrease refcount inside image object.
111        evas_object_image_data_set(context->image, context->pixels);
112    }
113    delete context;
114}
115
116void ewk_paint_context_save(Ewk_Paint_Context* context)
117{
118    EINA_SAFETY_ON_NULL_RETURN(context);
119
120    cairo_save(context->cairo.get());
121    context->graphicContext->save();
122}
123
124void ewk_paint_context_restore(Ewk_Paint_Context* context)
125{
126    EINA_SAFETY_ON_NULL_RETURN(context);
127
128    context->graphicContext->restore();
129    cairo_restore(context->cairo.get());
130}
131
132void ewk_paint_context_clip(Ewk_Paint_Context* context, const Eina_Rectangle* area)
133{
134    EINA_SAFETY_ON_NULL_RETURN(context);
135    EINA_SAFETY_ON_NULL_RETURN(area);
136
137    context->graphicContext->clip(WebCore::IntRect(*area));
138}
139
140void ewk_paint_context_scale(Ewk_Paint_Context* context, float scaleX, float scaleY)
141{
142    EINA_SAFETY_ON_NULL_RETURN(context);
143
144    context->graphicContext->scale(WebCore::FloatSize(scaleX, scaleY));
145}
146
147void ewk_paint_context_translate(Ewk_Paint_Context* context, float x, float y)
148{
149    EINA_SAFETY_ON_NULL_RETURN(context);
150
151    context->graphicContext->translate(x, y);
152}
153
154void ewk_paint_context_paint(Ewk_Paint_Context* context, WebCore::FrameView* view, const Eina_Rectangle* area)
155{
156    EINA_SAFETY_ON_NULL_RETURN(context);
157    EINA_SAFETY_ON_NULL_RETURN(view);
158    EINA_SAFETY_ON_NULL_RETURN(area);
159
160    WebCore::IntRect paintArea(*area);
161
162#if USE(TILED_BACKING_STORE)
163    if (view->frame()->tiledBackingStore()) {
164        int scrollX = view->scrollX();
165        int scrollY = view->scrollY();
166
167        context->graphicContext->translate(-scrollX, -scrollY);
168
169        paintArea.move(scrollX, scrollY);
170
171        view->frame()->tiledBackingStore()->paint(context->graphicContext.get(), paintArea);
172        return;
173    }
174#endif
175
176    if (view->isTransparent())
177        context->graphicContext->clearRect(paintArea);
178    view->paint(context->graphicContext.get(), paintArea);
179}
180
181void ewk_paint_context_paint_contents(Ewk_Paint_Context* context, WebCore::FrameView* view, const Eina_Rectangle* area)
182{
183    EINA_SAFETY_ON_NULL_RETURN(context);
184    EINA_SAFETY_ON_NULL_RETURN(view);
185    EINA_SAFETY_ON_NULL_RETURN(area);
186
187    WebCore::IntRect paintArea(*area);
188
189    if (view->isTransparent())
190        context->graphicContext->clearRect(paintArea);
191    view->paintContents(context->graphicContext.get(), paintArea);
192
193#if ENABLE(INSPECTOR)
194    WebCore::Page* page = view->frame()->page();
195    if (page) {
196        WebCore::InspectorController* controller = page->inspectorController();
197        if (controller->highlightedNode())
198            controller->drawHighlight(*context->graphicContext);
199    }
200#endif
201}
202