+++ /dev/null
-#include <ApplicationServices/ApplicationServices.h>
-
-#include "evas_common.h"
-#include "evas_private.h"
-#include "evas_engine.h"
-#include "Evas_Engine_Quartz.h"
-#include "evas_quartz_private.h"
-int _evas_engine_quartz_log_dom = -1;
-static Evas_Func func;
-
-typedef struct _Render_Engine Render_Engine;
-
-struct _Render_Engine
-{
- CGContextRef ctx;
- int w, h;
-
- struct
- {
- int redraw : 1;
- int x1, y1, x2, y2;
- } draw;
-};
-
-static inline void
-flip_pixels(int *y, int *h, void *re)
-{
- // We need to flip the Y axis, because Quartz uses a coordinate system
- // with the origin in the bottom left, while Evas uses a top left origin.
-
- (*y) = ((Evas_Quartz_Context *)re)->h - (*y);
-
- if (h && y) (*y) -= *h;
-}
-
-static void *
-eng_info(Evas *e)
-{
- Evas_Engine_Info_Quartz *info;
-
- info = calloc(1, sizeof(Evas_Engine_Info_Quartz));
- if (!info) return NULL;
- info->magic.magic = rand();
- info->render_mode = EVAS_RENDER_MODE_BLOCKING;
- return info;
-}
-
-static void
-eng_info_free(Evas *e, void *info)
-{
- free((Evas_Engine_Info_Quartz *)info);
-}
-
-static int
-eng_setup(Evas *e, void *in)
-{
- Render_Engine *re;
- Evas_Engine_Info_Quartz *info = (Evas_Engine_Info_Quartz *)in;
-
- if (!e->engine.data.output)
- e->engine.data.output = eng_output_setup(info->info.context, e->output.w, e->output.h);
- if (!e->engine.data.output) return 0;
-
- if (!e->engine.data.context)
- e->engine.data.context = e->engine.func->context_new(e->engine.data.output);
-
- ((Evas_Quartz_Context *)e->engine.data.context)->w = e->output.w;
- ((Evas_Quartz_Context *)e->engine.data.context)->h = e->output.h;
-
- return 1;
-}
-
-#pragma mark Output Setup
-
-static void *
-eng_output_setup(CGContextRef context, int w, int h)
-{
- Render_Engine *re = calloc(1, sizeof(Render_Engine));
- if (!re) return NULL;
-
- re->ctx = context;
- re->w = w;
- re->h = h;
-
- evas_common_cpu_init();
-
- evas_common_blend_init();
- evas_common_image_init();
- evas_common_convert_init();
- evas_common_scale_init();
- evas_common_rectangle_init();
- evas_common_polygon_init();
- evas_common_line_init();
- evas_common_font_init();
- evas_common_draw_init();
- evas_common_tilebuf_init();
-
- return re;
-}
-
-static void
-eng_output_free(void *data)
-{
- Render_Engine *re = (Render_Engine *)data;
-
- free(re);
-
- evas_common_font_shutdown();
- evas_common_image_shutdown();
-}
-
-static void
-eng_output_resize(void *data, int w, int h)
-{
- Render_Engine *re = (Render_Engine *)data;
-
- re->w = w;
- re->h = h;
-}
-
-static void
-eng_output_redraws_rect_add(void *data, int x, int y, int w, int h)
-{
- Render_Engine *re = (Render_Engine *)data;
-
- if (!re->draw.redraw)
- {
- re->draw.x1 = x;
- re->draw.y1 = y;
- re->draw.x2 = x + w;
- re->draw.y2 = y + h;
- }
- else
- {
- if (x < re->draw.x1) re->draw.x1 = x;
- if (y < re->draw.y1) re->draw.y1 = y;
- if ((x + w - 1) > re->draw.x2) re->draw.x2 = x + w - 1;
- if ((y + h - 1) > re->draw.y2) re->draw.y2 = y + h - 1;
- }
-
- re->draw.redraw = 1;
-}
-
-static void
-eng_output_redraws_rect_del(void *data, int x, int y, int w, int h)
-{
- // FIXME: Implement this?
-}
-
-static void
-eng_output_redraws_clear(void *data)
-{
- Render_Engine *re = (Render_Engine *)data;
-
- re->draw.redraw = 0;
-}
-
-static void *
-eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch)
-{
- Render_Engine *re = (Render_Engine *)data;
-
- if (!re->draw.redraw) return NULL;
-
- if (x) *x = re->draw.x1;
- if (y) *y = re->draw.y1;
- if (w) *w = re->draw.x2 - re->draw.x1 + 1;
- if (h) *h = re->draw.y2 - re->draw.y1 + 1;
- if (cx) *cx = re->draw.x1;
- if (cy) *cy = re->draw.y1;
- if (cw) *cw = re->draw.x2 - re->draw.x1 + 1;
- if (ch) *ch = re->draw.y2 - re->draw.y1 + 1;
-
- return re;
-}
-
-static void
-eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int w, int h)
-{
- Render_Engine *re = (Render_Engine *)data;
- Evas_Quartz_Context *ctx = (Evas_Quartz_Context *)(re->ctx);
- re->draw.redraw = 0;
-
- flip_pixels(&y, &h, ctx);
-
- CGContextClearRect(re->ctx, CGRectMake(x, y, w, h));
-}
-
-static void
-eng_output_flush(void *data)
-{
- // By default, Apple coalesces calls to CGContextFlush, but this actually
- // blocks if called more than 60 times per second, which is a waste of time.
- //
- // http://developer.apple.com/technotes/tn2005/tn2133.html
-
- CGContextFlush(((Render_Engine *)data)->ctx);
-}
-
-#pragma mark Context Manipulation
-
-static void *
-eng_context_new(void *data)
-{
- Evas_Quartz_Context *ctxt = calloc(1, sizeof(Evas_Quartz_Context));
- if (!ctxt) return NULL;
-
- return ctxt;
-}
-
-static void
-eng_context_free(void *data, void *context)
-{
- Render_Engine *re = (Render_Engine *)data;
- Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;
-
- if (re->ctx) CGContextRelease(re->ctx);
- free(ctxt);
-}
-
-static void
-eng_context_clip_set(void *data, void *context, int x, int y, int w, int h)
-{
- Render_Engine *re = (Render_Engine *)data;
- Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;
-
- flip_pixels(&y, &h, ctxt);
-
- CGContextResetClip(re->ctx);
- CGContextClipToRect(re->ctx, CGRectMake(0, 0, re->w, re->h)); // don't draw over the title bar
- CGContextClipToRect(re->ctx, CGRectMake(x, y, w, h));
-
- ctxt->clipped = 1;
-}
-
-static void
-eng_context_clip_unset(void *data, void *context)
-{
- Render_Engine *re = (Render_Engine *)data;
- Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;
-
- CGContextResetClip(re->ctx);
-
- ctxt->clipped = 0;
-}
-
-static int
-eng_context_clip_get(void *data, void *context, int *x, int *y, int *w, int *h)
-{
- Render_Engine *re = (Render_Engine *)data;
- Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;
-
- CGRect clip = CGContextGetClipBoundingBox(re->ctx);
- if (x) *x = clip.origin.x;
- if (y) *y = clip.origin.y;
- if (w) *w = clip.size.width;
- if (h) *h = clip.size.height;
-
- return ctxt->clipped;
-}
-
-static void
-eng_context_color_set(void *data, void *context, int r, int g, int b, int a)
-{
- Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;
-
- ctxt->col.r = (double)r / 255.0;
- ctxt->col.g = (double)g / 255.0;
- ctxt->col.b = (double)b / 255.0;
- ctxt->col.a = (double)a / 255.0;
-}
-
-static int
-eng_context_color_get(void *data, void *context, int *r, int *g, int *b, int *a)
-{
- Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;
-
- if (r) *r = ctxt->col.r * 255;
- if (g) *g = ctxt->col.g * 255;
- if (b) *b = ctxt->col.b * 255;
- if (a) *a = ctxt->col.a * 255;
- return 1;
-}
-
-static void
-eng_context_multiplier_set(void *data, void *context, int r, int g, int b, int a)
-{
- Render_Engine *re = (Render_Engine *)data;
- Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;
-
- ctxt->mul.r = (double)r / 255.0;
- ctxt->mul.g = (double)g / 255.0;
- ctxt->mul.b = (double)b / 255.0;
- ctxt->mul.a = (double)a / 255.0;
- ctxt->mul.set = 1;
-
- CGContextSetAlpha(re->ctx, ctxt->mul.a);
-}
-
-static void
-eng_context_multiplier_unset(void *data, void *context)
-{
- Render_Engine *re = (Render_Engine *)data;
- Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;
-
- ctxt->mul.set = 0;
- CGContextSetAlpha(re->ctx, 1.0);
-}
-
-static int
-eng_context_multiplier_get(void *data, void *context, int *r, int *g, int *b, int *a)
-{
- Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;
-
- if (r) *r = ctxt->mul.r * 255;
- if (g) *g = ctxt->mul.g * 255;
- if (b) *b = ctxt->mul.b * 255;
- if (a) *a = ctxt->mul.a * 255;
- return ctxt->mul.set;
-}
-
-static void
-eng_context_cutout_add(void *data, void *context, int x, int y, int w, int h)
-{
- // FIXME: This doesn't seem to be implemented anywhere. What does it do?
-}
-
-static void
-eng_context_cutout_clear(void *data, void *context)
-{
- // FIXME: This doesn't seem to be implemented anywhere. What does it do?
-}
-
-static void
-eng_context_anti_alias_set(void *data, void *context, unsigned char aa)
-{
- Render_Engine *re = (Render_Engine *)data;
- Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;
-
- ctxt->aa = aa;
-
- CGContextSetAllowsAntialiasing(re->ctx, (bool)aa);
- CGContextSetShouldAntialias(re->ctx, (bool)aa);
- CGContextSetInterpolationQuality(re->ctx, kCGInterpolationLow); // is it OK to assume low quality?
-}
-
-static unsigned char
-eng_context_anti_alias_get(void *data, void *context)
-{
- Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;
-
- return ctxt->aa;
-}
-
-#pragma mark Rectangle Drawing
-
-static void
-eng_rectangle_draw(void *data, void *context, void *surface, int x, int y, int w, int h)
-{
- Render_Engine *re = (Render_Engine *)data;
- Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;
- double r, g, b, a;
-
- flip_pixels(&y, &h, ctxt);
-
- r = ctxt->col.r;
- g = ctxt->col.g;
- b = ctxt->col.b;
- a = ctxt->col.a;
-
- if (ctxt->mul.set)
- {
- r *= ctxt->mul.r;
- g *= ctxt->mul.g;
- b *= ctxt->mul.b;
- a *= ctxt->mul.a;
- }
-
- CGContextSetRGBFillColor(re->ctx, r, g, b, a);
- CGContextFillRect(re->ctx, CGRectMake(x, y, w, h));
-}
-
-#pragma mark Line Drawing
-
-static void
-eng_line_draw(void *data, void *context, void *surface, int x1, int y1, int x2, int y2)
-{
- Render_Engine *re = (Render_Engine *)data;
- Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;
- double r, g, b, a;
-
- flip_pixels(&y1, NULL, ctxt);
- flip_pixels(&y2, NULL, ctxt);
-
- r = ctxt->col.r;
- g = ctxt->col.g;
- b = ctxt->col.b;
- a = ctxt->col.a;
-
- if (ctxt->mul.set)
- {
- r *= ctxt->mul.r;
- g *= ctxt->mul.g;
- b *= ctxt->mul.b;
- a *= ctxt->mul.a;
- }
-
- CGContextSetRGBStrokeColor(re->ctx, r, g, b, a);
- CGContextBeginPath(re->ctx);
- CGContextMoveToPoint(re->ctx, x1, y1);
- CGContextAddLineToPoint(re->ctx, x2, y2);
- CGContextStrokePath(re->ctx);
-}
-
-#pragma mark Polygon Manipulation & Drawing
-
-static void *
-eng_polygon_point_add(void *data, void *context, void *polygon, int x, int y)
-{
- Evas_Quartz_Polygon *poly;
- Evas_Quartz_Polygon_Point *pt;
- Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;
-
- flip_pixels(&y, NULL, ctxt);
-
- poly = (Evas_Quartz_Polygon *)polygon;
- if (!poly) poly = calloc(1, sizeof(Evas_Quartz_Polygon));
- if (!poly) return NULL;
-
- pt = calloc(1, sizeof(Evas_Quartz_Polygon_Point));
- if (pt)
- {
- pt->x = x;
- pt->y = y;
- poly->points = eina_list_append(poly->points, pt);
- }
- return poly;
-}
-
-static void *
-eng_polygon_points_clear(void *data, void *context, void *polygon)
-{
- Evas_Quartz_Polygon *poly;
-
- poly = (Evas_Quartz_Polygon *)polygon;
- if (!poly) return NULL;
-
- while (poly->points)
- {
- free(poly->points->data);
- poly->points = eina_list_remove_list(poly->points, poly->points);
- }
- free(poly);
-
- return NULL;
-}
-
-static void
-eng_polygon_draw(void *data, void *context, void *surface, void *polygon)
-{
- Render_Engine *re = (Render_Engine *)data;
- Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;
- Evas_Quartz_Polygon *poly = (Evas_Quartz_Polygon *)polygon;
- Evas_Quartz_Polygon_Point *pt;
-
- double r, g, b, a;
-
- CGContextBeginPath(re->ctx);
-
- pt = poly->points->data;
- if (pt)
- {
- Eina_List *l;
- CGContextMoveToPoint(re->ctx, pt->x, pt->y);
- EINA_LIST_FOREACH(poly->points->next, l, pt)
- CGContextAddLineToPoint(re->ctx, pt->x, pt->y);
- }
-
- r = ctxt->col.r;
- g = ctxt->col.g;
- b = ctxt->col.b;
- a = ctxt->col.a;
-
- if (ctxt->mul.set)
- {
- r *= ctxt->mul.r;
- g *= ctxt->mul.g;
- b *= ctxt->mul.b;
- a *= ctxt->mul.a;
- }
-
- CGContextSetRGBFillColor(re->ctx, r, g, b, a);
- CGContextFillPath(re->ctx);
-}
-
-#pragma mark Image Manipulation & Drawing
-
-static void *
-eng_image_load(void *data, const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo)
-{
- Evas_Quartz_Image *im = calloc(1, sizeof(Evas_Quartz_Image));
-
- // FIXME: set error before returning without a new image...
- // I can't figure out what to set it to, even trying to follow through the core code.
- // Also, none of the other engines set it.
-
- if (!im)
- {
- *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
- return NULL;
- }
-
- *error = EVAS_LOAD_ERROR_NONE;
- im->im = (RGBA_Image *)evas_common_load_image_from_file(file, key, lo, error);
- if (!im->im)
- {
- free(im);
- return NULL;
- }
- im->references = 1;
- return im;
-}
-
-static void *
-eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace)
-{
- Evas_Quartz_Image *im = calloc(1, sizeof(Evas_Quartz_Image));
-
- if (!im) return NULL;
-
- im->im = (RGBA_Image *)evas_cache_image_data(evas_common_image_cache_get(), w, h, image_data, alpha, cspace);
- im->references = 1;
-
- if (!im->im)
- {
- free(im);
- return NULL;
- }
-
- return im;
-}
-
-static void *
-eng_image_new_from_copied_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace)
-{
- Evas_Quartz_Image *im = calloc(1, sizeof(Evas_Quartz_Image));
-
- if (!im) return NULL;
-
- im->im = (RGBA_Image *)evas_cache_image_copied_data(evas_common_image_cache_get(), w, h, image_data, alpha, cspace);
- im->references = 1;
-
- if (!im->im)
- {
- free(im);
- return NULL;
- }
-
- return im;
-}
-
-static void
-eng_image_free(void *data, void *image)
-{
- Evas_Quartz_Image *im = (Evas_Quartz_Image *)image;
-
- if (!im) return;
-
- if (--im->references > 0) return;
-
- if (im->cgim) CGImageRelease(im->cgim);
- if (im->im) evas_cache_image_drop(&im->im->cache_entry);
- free(im);
-}
-
-static void
-eng_image_data_preload_request(void *data __UNUSED__, void *image, const void *target)
-{
- Evas_Quartz_Image *im = (Evas_Quartz_Image *)image;
-
- if (!im || !im->im) return ;
- evas_cache_image_preload_data(&im->im->cache_entry, target);
-}
-
-static void
-eng_image_data_preload_cancel(void *data __UNUSED__, void *image, const void *target)
-{
- Evas_Quartz_Image *im = (Evas_Quartz_Image *)image;
-
- if (!im || !im->im) return ;
- evas_cache_image_preload_cancel(&im->im->cache_entry, target);
-}
-
-static void *
-eng_image_size_set(void *data, void *image, int w, int h)
-{
- Evas_Quartz_Image *im = (Evas_Quartz_Image *)image;
- Evas_Quartz_Image *im_old;
-
- if (!im) return NULL;
- im_old = image;
- if ((eng_image_colorspace_get(data, image) == EVAS_COLORSPACE_YCBCR422P601_PL) ||
- (eng_image_colorspace_get(data, image) == EVAS_COLORSPACE_YCBCR422P709_PL))
- w &= ~0x1;
-
- if ((im_old) && (im_old->im->cache_entry.w == w) && (im_old->im->cache_entry.h == h))
- return image;
-
- if ((w <= 0) || (h <= 0))
- {
- eng_image_free(data, im_old);
- return NULL;
- }
-
- if (im_old)
- {
- im = eng_image_new_from_data(data, w, h, im_old->im->image.data, eng_image_alpha_get(data, im_old), eng_image_colorspace_get(data, im_old));
- eng_image_free(data, im_old);
- }
- else
- im = eng_image_new_from_data(data, w, h, NULL, true, EVAS_COLORSPACE_ARGB8888);
- return im;
-}
-
-static void
-eng_image_size_get(void *data, void *image, int *w, int *h)
-{
- Evas_Quartz_Image *im = (Evas_Quartz_Image *)image;
-
- if (!image)
- {
- if (w) *w = 0;
- if (h) *h = 0;
- }
- else
- {
- if (w) *w = im->im->cache_entry.w;
- if (h) *h = im->im->cache_entry.h;
- }
-}
-
-static void *
-eng_image_dirty_region(void *data, void *image, int x, int y, int w, int h)
-{
- Evas_Quartz_Image *im = (Evas_Quartz_Image *)image;
-
- if ((im) && (im->im))
- return evas_cache_image_dirty(&im->im->cache_entry, x, y, w, h);
-}
-
-static void *
-eng_image_alpha_set(void *data, void *image, int has_alpha)
-{
- Evas_Quartz_Image *im = (Evas_Quartz_Image *)image;
-
- if ((!im) || (!im->im)) return NULL;
-
- if (im->im->cache_entry.space != EVAS_COLORSPACE_ARGB8888)
- {
- im->im->cache_entry.flags.alpha = 0;
- }
- else
- {
- im->im = (RGBA_Image *)evas_cache_image_alone(&im->im->cache_entry);
- evas_common_image_colorspace_dirty(im->im);
- im->im->cache_entry.flags.alpha = has_alpha ? 1 : 0;
- }
-
- return im;
-}
-
-static int
-eng_image_alpha_get(void *data, void *image)
-{
- Evas_Quartz_Image *im = (Evas_Quartz_Image *) image;
-
- if (!im->im) return 0;
-
- return (int)(im->im->cache_entry.flags.alpha);
-}
-
-static char *
-eng_image_comment_get(void *data, void *image, char *key)
-{
- Evas_Quartz_Image *im = (Evas_Quartz_Image *)image;
-
- if ((!im) || (!im->im))
- return NULL;
- else
- return im->im->info.comment;
-}
-
-static char *
-eng_image_format_get(void *data, void *image)
-{
- // these are unimplemented for now, until core features are finished
-
- return NULL;
-}
-
-static void
-eng_image_colorspace_set(void *data, void *image, int cspace)
-{
- Evas_Quartz_Image *im = (Evas_Quartz_Image *)image;
-
- if (!im)
- return;
- else
- evas_cache_image_colorspace(&im->im->cache_entry, cspace);
-}
-
-static int
-eng_image_colorspace_get(void *data, void *image)
-{
- Evas_Quartz_Image *im = (Evas_Quartz_Image *)image;
-
- if (!im)
- return EVAS_COLORSPACE_ARGB8888;
- else
- return im->im->cache_entry.space;
-}
-
-static void
-eng_image_native_set(void *data, void *image, void *native)
-{
- // these are unimplemented for now, until core features are finished
-}
-
-static void *
-eng_image_native_get(void *data, void *image)
-{
- // these are unimplemented for now, until core features are finished
- return NULL;
-}
-
-static void *
-eng_image_data_put(void *data, void *image, DATA32 *image_data)
-{
- // FIXME: one last leak somewhere in this function
-
- Evas_Quartz_Image *im_old = (Evas_Quartz_Image *)image;
-
- if (!im_old) return NULL;
-
- if (im_old->cgim)
- {
- CGImageRelease(im_old->cgim);
- im_old->cgim = NULL;
- }
-
- switch (im_old->im->cache_entry.space)
- {
- case EVAS_COLORSPACE_ARGB8888:
- image = eng_image_new_from_data(data, im_old->im->cache_entry.w, im_old->im->cache_entry.h, image_data, 1, EVAS_COLORSPACE_ARGB8888);
- eng_image_free(data, im_old);
- break;
- case EVAS_COLORSPACE_YCBCR422P709_PL:
- case EVAS_COLORSPACE_YCBCR422P601_PL:
- if (image_data != im_old->im->cs.data)
- {
- if (im_old->im->cs.data)
- if (!im_old->im->cs.no_free)
- free(im_old->im->cs.data);
-
- im_old->im->cs.data = image_data;
- evas_common_image_colorspace_dirty(im_old->im);
- }
- break;
- }
-
- if (!image) return NULL;
-
- return image;
-}
-
-static void *
-eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data)
-{
- Evas_Quartz_Image *im = (Evas_Quartz_Image *)image;
-
- if ((!im) || (!im->im))
- {
- *image_data = NULL;
- return NULL;
- }
-
- switch (im->im->cache_entry.space)
- {
- case EVAS_COLORSPACE_ARGB8888:
- if (to_write)
- {
- CGImageRelease(im->cgim);
- im->cgim = NULL;
-
- if (im->references > 1)
- {
- Evas_Quartz_Image *im_new;
- im_new = eng_image_new_from_copied_data(data,
- im->im->cache_entry.w,
- im->im->cache_entry.h,
- im->im->image.data,
- eng_image_alpha_get(data, image),
- eng_image_colorspace_get(data, image));
-
- if (!im_new)
- {
- if (image_data) *image_data = NULL;
- return im;
- }
-
- eng_image_free(data, im);
- im = im_new;
- }
- else
- {
- im->im = (RGBA_Image *)evas_cache_image_dirty(&im->im->cache_entry,
- 0, 0,
- im->im->cache_entry.w, im->im->cache_entry.h);
- im->references++;
- }
- }
-
- evas_cache_image_load_data(&im->im->cache_entry);
-
- if (image_data) *image_data = im->im->image.data;
- break;
- case EVAS_COLORSPACE_YCBCR422P709_PL:
- case EVAS_COLORSPACE_YCBCR422P601_PL:
- if (image_data) *image_data = im->im->cs.data;
- im->references++;
- break;
- default:
- abort(); // this seems ... incredibly unreasonable, but GL does it...
- break;
- }
-
- return im;
-}
-
-static void
-eng_image_draw(void *data, void *context, void *surface, void *image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int smooth)
-{
- Render_Engine *re = (Render_Engine *)data;
- Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;
- Evas_Quartz_Image *im = (Evas_Quartz_Image *)image;
- flip_pixels(&dst_y, &dst_h, ctxt);
-
- if ((!im) || (!im->im)) return;
-
- if (!im->cgim)
- {
- CGColorSpaceRef colorspace;
- CGDataProviderRef provider;
- evas_cache_image_load_data(&im->im->cache_entry);
- evas_common_image_colorspace_normalize((RGBA_Image *)(&im->im->cache_entry));
-
- if (!im->im->image.data) return;
-
- colorspace = CGColorSpaceCreateDeviceRGB();
- provider = CGDataProviderCreateWithData(NULL,
- im->im->image.data,
- im->im->cache_entry.w * im->im->cache_entry.h * sizeof(DATA32),
- NULL);
- im->cgim = CGImageCreate(im->im->cache_entry.w,
- im->im->cache_entry.h,
- 8,
- 8 * 4,
- 4 * im->im->cache_entry.w,
- colorspace,
- kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
- provider,
- NULL,
- smooth,
- kCGRenderingIntentDefault);
-
- CGDataProviderRelease(provider);
- CGColorSpaceRelease(colorspace);
-
- if (!im->cgim) return;
- }
-
- CGImageRef subImage = NULL;
-
- if (src_x != 0 || src_y != 0 || src_w != 0 || src_h != 0)
- {
- subImage = CGImageCreateWithImageInRect(im->cgim, CGRectMake(src_x,src_y,src_w,src_h));
- if (!subImage) return;
-
- CGContextDrawImage(re->ctx, CGRectMake(dst_x, dst_y, dst_w, dst_h), subImage);
- CGImageRelease(subImage);
- }
- else
- CGContextDrawImage(re->ctx, CGRectMake(dst_x, dst_y, dst_w, dst_h), im->cgim);
-}
-
-static void
-eng_image_scale_hint_set(void *data __UNUSED__, void *image, int hint)
-{
-}
-
-static int
-eng_image_scale_hint_get(void *data __UNUSED__, void *image)
-{
- return EVAS_IMAGE_SCALE_HINT_NONE;
-}
-
-
-#pragma mark Text Manipulation & Drawing
-
-static Evas_Quartz_Font *
-quartz_font_from_ats(ATSFontContainerRef container, int size)
-{
- ItemCount count;
- ATSFontRef *fonts;
- CTFontRef font;
- CFStringRef keys[1];
- CFTypeRef values[1];
- CFDictionaryRef attr;
- Evas_Quartz_Font *loaded_font;
-
- ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 0, NULL, &count);
- fonts = calloc(count, sizeof(ATSFontRef));
- if (!fonts) return NULL;
- ATSFontFindFromContainer(container, kATSOptionFlagsDefault, count, fonts, NULL);
-
- font = CTFontCreateWithPlatformFont(fonts[0], size, NULL, NULL);
-
- loaded_font = calloc(1, sizeof(Evas_Quartz_Font));
- if (!font || !loaded_font)
- {
- if (loaded_font) free(loaded_font);
- if (fonts) free(fonts);
- if (font) CFRelease(font);
- return NULL;
- }
-
- keys[0] = kCTFontAttributeName;
- values[0] = font;
- attr = CFDictionaryCreate(NULL,
- (const void **)&keys,
- (const void **)&values,
- sizeof(keys) / sizeof(keys[0]),
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
-
- loaded_font->font = font;
- loaded_font->attr = attr;
- loaded_font->size = size;
-
- free(fonts);
-
- return loaded_font;
-}
-
-static void *
-eng_font_add(void *data, void *font, const char *name, int size)
-{
- // FIXME: what is this function supposed to do?
- // if I delete it, we eventually crash when it gets run
-
- return (char *)name;
-}
-
-static void *
-eng_font_load(void *data, const char *name, int size)
-{
- FSRef fontFile;
- ATSFontContainerRef container;
-
- FSPathMakeRef((unsigned char *)name, &fontFile, NULL);
- ATSFontActivateFromFileReference(&fontFile, kATSFontContextLocal, kATSFontFormatUnspecified, NULL, kATSOptionFlagsDefault, &container);
-
- return quartz_font_from_ats(container, size);;
-}
-
-static void *
-eng_font_memory_load(void *data, char *name, int size, const void *fdata, int fdata_size)
-{
- ATSFontContainerRef container;
-
- ATSFontActivateFromMemory((void *)fdata, fdata_size, kATSFontContextLocal, kATSFontFormatUnspecified, NULL, kATSOptionFlagsDefault, &container);
-
- return quartz_font_from_ats(container, size);
-}
-
-static void
-eng_font_free(void *data, void *font)
-{
- Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font;
-
- CFRelease(loaded_font->font);
- CFRelease(loaded_font->attr);
- free(loaded_font);
-}
-
-static int
-eng_font_ascent_get(void *data, void *font)
-{
- Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font;
-
- return CTFontGetAscent(loaded_font->font);
-}
-
-static int
-eng_font_descent_get(void *data, void *font)
-{
- Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font;
-
- return CTFontGetDescent(loaded_font->font);
-}
-
-static int
-eng_font_max_ascent_get(void *data, void *font)
-{
- Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font;
-
- return CTFontGetAscent(loaded_font->font);
-}
-
-static int
-eng_font_max_descent_get(void *data, void *font)
-{
- Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font;
-
- return CTFontGetDescent(loaded_font->font);
-}
-
-static void
-eng_font_string_size_get(void *data, void *font, const char *text, const Evas_Text_Props *text_props, int *w, int *h)
-{
- Render_Engine *re = (Render_Engine *)data;
- Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font;
-
- CFStringRef string = CFStringCreateWithCString(NULL, text, kCFStringEncodingUTF8);
- CFAttributedStringRef attrString = CFAttributedStringCreate(NULL, string, loaded_font->attr);
- CTLineRef line = CTLineCreateWithAttributedString(attrString);
- CGContextSetTextMatrix(re->ctx, CGAffineTransformIdentity);
- CGContextSetTextPosition(re->ctx, 0, CTFontGetDescent(loaded_font->font));
- CGRect bounds = CTLineGetImageBounds(line, re->ctx);
-
- // Descenders on characters seem to leave origin at typographic origin, instead of image origin.
- // Evas expects text to be treated like an image, so we have to offset by the typographic origin.
-
- if (w) (*w) = ceil(bounds.size.width + bounds.origin.x);
- if (h) (*h) = ceil(bounds.size.height + bounds.origin.y);
-
- CFRelease(attrString);
- CFRelease(string);
- CFRelease(line);
-}
-
-static int
-eng_font_inset_get(void *data, void *font, const Evas_Text_Props *intl_props)
-{
- return 0;
-}
-
-static int
-eng_font_h_advance_get(void *data, void *font, const char *text, const Evas_Text_Props *text_props)
-{
- int w;
-
- eng_font_string_size_get(data, font, text, text_props, &w, NULL);
-
- return w + 2; // FIXME: shouldn't need a constant here. from where do we get word spacing?
- // it seems we lose the space between differently-styled text in a text block. Why?
-}
-
-static int
-eng_font_v_advance_get(void *data, void *font, const char *text, const Evas_Text_Props *text_props)
-{
- int h;
-
- eng_font_string_size_get(data, font, text, text_props, NULL, &h);
-
- return h;
-}
-
-static int
-eng_font_char_coords_get(void *data, void *font, const char *text, const Evas_Text_Props *text_props, int pos, int *cx, int *cy, int *cw, int *ch)
-{
- Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font;
-
- CFStringRef string = CFStringCreateWithCString(NULL, text, kCFStringEncodingUTF8);
- CFAttributedStringRef attrString = CFAttributedStringCreate(NULL, string, loaded_font->attr);
- CTLineRef line = CTLineCreateWithAttributedString(attrString);
-
- float offset = CTLineGetOffsetForStringIndex(line, pos, NULL);
- if (cx) *cx = offset;
- if (cy) *cy = loaded_font->size;
-
- CFRelease(attrString);
- CFRelease(string);
- CFRelease(line);
-
- return 1;
-}
-
-/*FIXME: this is *NOT* implemennted correctly, look at the other engines to
- * see what needed to be done */
-static int
-eng_font_pen_coords_get(void *data, void *font, const char *text, const Evas_Text_Props *text_props, int pos, int *cpen_x, int *cy, int *cadv, int *ch)
-{
- return eng_font_char_coords_get(data, font, text, text_props, pos, cpen_x,
- cy, cadv, ch);
-}
-
-static Eina_Bool
-eng_font_text_props_info_create(void *data __UNUSED__, void *font, Eina_Unicode *text, Evas_Text_Props *text_props, const Evas_BiDi_Paragraph_Props *par_props, size_t pos, size_t len)
-{
- (void) font;
- (void) text;
- (void) text_props;
- (void) par_props;
- (void) pos;
- (void) len;
-#if !defined(OT_SUPPORT) && defined(BIDI_SUPPORT)
- evas_bidi_shape_string(text, par_props, pos, len);
-#endif
- return evas_common_text_props_content_create(font, text, text_props, len);
-}
-
-static int
-eng_font_char_at_coords_get(void *data, void *font, const char *text, const Evas_Text_Props *text_props, int x, int y, int *cx, int *cy, int *cw, int *ch)
-{
- // Return the index of the character at the given point, also lookup it's origin x, y, w, and h.
- Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font;
-
- CFStringRef string = CFStringCreateWithCString(NULL, text, kCFStringEncodingUTF8);
- CFAttributedStringRef attrString = CFAttributedStringCreate(NULL, string, loaded_font->attr);
- CTLineRef line = CTLineCreateWithAttributedString(attrString);
-
- int stringIndex = (int) CTLineGetStringIndexForPosition(line, CGPointMake(x, y));
-
- // In order to get the character's size and position, look up the position of this character and the next one
- eng_font_char_coords_get(data, font, text, text_props, stringIndex, cx, cy, NULL, NULL);
- eng_font_char_coords_get(data, font, text, text_props, stringIndex + 1, cw, NULL, NULL, NULL);
-
- if (cw && cx) *cw -= *cx;
- if (ch) *ch = loaded_font->size;
-
- CFRelease(attrString);
- CFRelease(string);
- CFRelease(line);
-
- return stringIndex;
-}
-
-static void
-eng_font_hinting_set(void *data, void *font, int hinting)
-{
- Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font;
- loaded_font->hint = hinting;
-}
-
-static int
-eng_font_hinting_can_hint(void *data, int hinting)
-{
- return 1;
-}
-
-static void
-eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text, const Evas_Text_Props *text_props)
-{
- Render_Engine *re = (Render_Engine *)data;
- Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;
- Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font;
- double r, g, b, a;
- CGFloat colors[4];
- CGColorSpaceRef colorspace;
- CGColorRef color;
- CFStringRef keys[2];
- CFTypeRef values[2];
- CFDictionaryRef attr;
- CFStringRef string;
- CFAttributedStringRef attrString;
- CTLineRef line;
-
- flip_pixels(&y, &h, ctxt);
-
- // FIXME: I know this should never happen, but the next line is magic.
- // It's also... broken. It /works/, but ... for example, subtracting 1 shouldn't need to happen.
- // The text drawing is a mess, but this is the closest I've gotten yet...
-
- y += floor(CTFontGetAscent(loaded_font->font) - (CTFontGetXHeight(loaded_font->font) + CTFontGetDescent(loaded_font->font))) - 1;
-
- CGContextSetShouldSmoothFonts(re->ctx, (bool)(loaded_font->hint));
-
- r = ctxt->col.r;
- g = ctxt->col.g;
- b = ctxt->col.b;
- a = ctxt->col.a;
-
- if (ctxt->mul.set)
- {
- r *= ctxt->mul.r;
- g *= ctxt->mul.g;
- b *= ctxt->mul.b;
- a *= ctxt->mul.a;
- }
-
- colors[0] = r;
- colors[1] = g;
- colors[2] = b;
- colors[3] = a;
-
- // Create an attributed string
- colorspace = CGColorSpaceCreateDeviceRGB();
- color = CGColorCreate(colorspace, colors);
-
- keys[0] = kCTFontAttributeName;
- values[0] = loaded_font->font;
- keys[1] = kCTForegroundColorAttributeName;
- values[1] = color;
-
- attr = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- string = CFStringCreateWithCString(NULL, text, kCFStringEncodingUTF8);
- attrString = CFAttributedStringCreate(NULL, string, attr);
-
- // Draw the string
- line = CTLineCreateWithAttributedString(attrString);
- CGContextSetTextMatrix(re->ctx, CGAffineTransformIdentity);
- CGContextSetTextPosition(re->ctx, x, y + h);
- CTLineDraw(line, re->ctx);
-
- // Clean up
- CGColorSpaceRelease(colorspace);
- CFRelease(attr);
- CFRelease(string);
- CFRelease(attrString);
- CFRelease(line);
- CGColorRelease(color);
-}
-
-#pragma mark Module Function Export
-
-static int
-module_open(Evas_Module *em)
-{
- if (!em) return 0;
-
- if (!_evas_module_engine_inherit(&func, "software_generic")) return 0;
-
- _evas_engine_quartz_log_dom = eina_log_domain_register
- ("evas-quartz", EVAS_DEFAULT_LOG_COLOR);
- if (_evas_engine_quartz_log_dom < 0)
- {
- EINA_LOG_ERR("Can not create a module log domain.");
- return 0;
- }
-
- #define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
- ORD(context_anti_alias_get);
- ORD(context_anti_alias_set);
- ORD(context_clip_get);
- ORD(context_clip_set);
- ORD(context_clip_unset);
- ORD(context_color_get);
- ORD(context_color_set);
- ORD(context_cutout_add);
- ORD(context_cutout_clear);
- ORD(context_free);
- ORD(context_multiplier_get);
- ORD(context_multiplier_set);
- ORD(context_multiplier_unset);
- ORD(context_new);
- ORD(font_add);
- ORD(font_ascent_get);
- ORD(font_char_at_coords_get);
- ORD(font_char_coords_get);
- ORD(font_descent_get);
- ORD(font_draw);
- ORD(font_free);
- ORD(font_hinting_can_hint);
- ORD(font_hinting_set);
- ORD(font_h_advance_get);
- ORD(font_inset_get);
- ORD(font_load);
- ORD(font_max_ascent_get);
- ORD(font_max_descent_get);
- ORD(font_memory_load);
- ORD(font_string_size_get);
- ORD(font_v_advance_get);
- ORD(image_alpha_get);
- ORD(image_alpha_set);
- ORD(image_colorspace_get);
- ORD(image_colorspace_set);
- ORD(image_comment_get);
- ORD(image_data_get);
- ORD(image_data_put);
- ORD(image_data_preload_request);
- ORD(image_data_preload_cancel);
- ORD(image_dirty_region);
- ORD(image_draw);
- ORD(image_format_get);
- ORD(image_free);
- ORD(image_load);
- ORD(image_native_get);
- ORD(image_native_set);
- ORD(image_new_from_copied_data);
- ORD(image_new_from_data);
- ORD(image_size_get);
- ORD(image_size_set);
- ORD(info);
- ORD(info_free);
- ORD(line_draw);
- ORD(output_flush);
- ORD(output_free);
- ORD(output_redraws_clear);
- ORD(output_redraws_next_update_get);
- ORD(output_redraws_next_update_push);
- ORD(output_redraws_rect_add);
- ORD(output_redraws_rect_del);
- ORD(output_resize);
- ORD(polygon_draw);
- ORD(polygon_points_clear);
- ORD(polygon_point_add);
- ORD(rectangle_draw);
- ORD(setup);
-
- ORD(image_scale_hint_set);
- ORD(image_scale_hint_get);
-
-// ORD(image_map_draw);
-// ORD(image_map_surface_new);
-// ORD(image_map_surface_free);
- /* now advertise out our api */
- em->functions = (void *)(&func);
- return 1;
-}
-
-static void
-module_close(Evas_Module *em)
-{
- eina_log_domain_unregister(_evas_engine_quartz_log_dom);
-}
-
-static Evas_Module_Api evas_modapi =
-{
- EVAS_MODULE_API_VERSION,
- "quartz",
- "none",
- {
- module_open,
- module_close
- }
-};
-
-EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, quartz);
-
-#ifndef EVAS_STATIC_BUILD_QUARTZ
-EVAS_EINA_MODULE_DEFINE(engine, quartz);
-#endif
+++ /dev/null
-#ifndef _EVAS_QUARTZ_PRIVATE_H_
-#define _EVAS_QUARTZ_PRIVATE_H_
-
-#include "evas_common.h"/* Also includes international specific stuff */
-#include "evas_engine.h"
-
-CG_EXTERN void CGContextResetClip (CGContextRef); // undocumented CoreGraphics function to clear clip rect
-
-static inline void flip_pixels(int *y, int *h, void *re);
-
-static void *eng_info(Evas *e);
-static void eng_info_free(Evas *e, void *info);
-
-static void *eng_output_setup(CGContextRef context, int w, int h);
-static int eng_setup(Evas *e, void *in);
-
-static void eng_output_free(void *data);
-static void eng_output_resize(void *data, int w, int h);
-static void eng_output_redraws_rect_add(void *data, int x, int y, int w, int h);
-static void eng_output_redraws_rect_del(void *data, int x, int y, int w, int h);
-static void eng_output_redraws_clear(void *data);
-static void *eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch);
-static void eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int w, int h);
-static void eng_output_flush(void *data);
-
-static void *eng_context_new(void *data);
-static void eng_context_free(void *data, void *context);
-static void eng_context_clip_set(void *data, void *context, int x, int y, int w, int h);
-static void eng_context_clip_unset(void *data, void *context);
-static int eng_context_clip_get(void *data, void *context, int *x, int *y, int *w, int *h);
-static void eng_context_color_set(void *data, void *context, int r, int g, int b, int a);
-static int eng_context_color_get(void *data, void *context, int *r, int *g, int *b, int *a);
-static void eng_context_multiplier_set(void *data, void *context, int r, int g, int b, int a);
-static void eng_context_multiplier_unset(void *data, void *context);
-static int eng_context_multiplier_get(void *data, void *context, int *r, int *g, int *b, int *a);
-static void eng_context_cutout_add(void *data, void *context, int x, int y, int w, int h);
-static void eng_context_cutout_clear(void *data, void *context);
-static void eng_context_anti_alias_set(void *data, void *context, unsigned char aa);
-static unsigned char eng_context_anti_alias_get(void *data, void *context);
-
-static void eng_rectangle_draw(void *data, void *context, void *surface, int x, int y, int w, int h);
-
-static void eng_line_draw(void *data, void *context, void *surface, int x1, int y1, int x2, int y2);
-
-static void *eng_polygon_point_add(void *data, void *context, void *polygon, int x, int y);
-static void *eng_polygon_points_clear(void *data, void *context, void *polygon);
-static void eng_polygon_draw(void *data, void *context, void *surface, void *polygon);
-
-static void *eng_image_load(void *data, const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo);
-
-static void *eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace);
-static void *eng_image_new_from_copied_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace);
-static void eng_image_free(void *data, void *image);
-static void eng_image_size_get(void *data, void *image, int *w, int *h);
-static void *eng_image_dirty_region(void *data, void *image, int x, int y, int w, int h);
-static void *eng_image_alpha_set(void *data, void *image, int has_alpha);
-static int eng_image_alpha_get(void *data, void *image);
-static char *eng_image_comment_get(void *data, void *image, char *key);
-static char *eng_image_format_get(void *data, void *image);
-static void eng_image_colorspace_set(void *data, void *image, int cspace);
-static int eng_image_colorspace_get(void *data, void *image);
-static void eng_image_native_set(void *data, void *image, void *native);
-static void *eng_image_native_get(void *data, void *image);
-static void *eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data);
-static void *eng_image_data_put(void *data, void *image, DATA32 *image_data);
-static void *eng_image_size_set(void *data, void *image, int w, int h);
-static void eng_image_draw(void *data, void *context, void *surface, void *image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int smooth);
-
-static void *eng_font_add(void *data, void *font, const char *name, int size);
-static Evas_Quartz_Font *quartz_font_from_ats(ATSFontContainerRef container, int size);
-static void *eng_font_load(void *data, const char *name, int size);
-static void *eng_font_memory_load(void *data, char *name, int size, const void *fdata, int fdata_size);
-static void eng_font_free(void *data, void *font);
-static int eng_font_ascent_get(void *data, void *font);
-static int eng_font_descent_get(void *data, void *font);
-static int eng_font_max_ascent_get(void *data, void *font);
-static int eng_font_max_descent_get(void *data, void *font);
-static void eng_font_string_size_get(void *data, void *font, const char *text, const Evas_Text_Props *intl_props, int *w, int *h);
-static int eng_font_inset_get(void *data, void *font, const Evas_Text_Props *intl_props);
-static int eng_font_right_inset_get(void *data, void *font, const Evas_Text_Props *intl_props);
-static int eng_font_h_advance_get(void *data, void *font, const char *text, const Evas_Text_Props *intl_props);
-static int eng_font_v_advance_get(void *data, void *font, const char *text, const Evas_Text_Props *intl_props);
-static int eng_font_char_coords_get(void *data, void *font, const char *text, const Evas_Text_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch);
-static int eng_font_pen_coords_get(void *data, void *font, const char *text, const Evas_Text_Props *intl_props, int pos, int *cpen_x, int *cy, int *cadv, int *ch);
-static Eina_Bool eng_font_text_props_info_create(void *data __UNUSED__, void *font, Eina_Unicode *text, Evas_Text_Props *intl_props, const Evas_BiDi_Paragraph_Props *par_props, size_t pos, size_t len);
-static int eng_font_char_at_coords_get(void *data, void *font, const char *text, const Evas_Text_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch);
-static void eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text, const Evas_Text_Props *intl_props);
-static void eng_font_hinting_set(void *data, void *font, int hinting);
-static int eng_font_hinting_can_hint(void *data, int hinting);
-
-#endif /* _EVAS_QUARTZ_PRIVATE_H_ */