/src/canvas/skia/ftk_canvas_skia.cpp

http://ftk.googlecode.com/ · C++ · 322 lines · 233 code · 61 blank · 28 comment · 25 complexity · c4415b11904b6f0b7bcbf46adc88bdba MD5 · raw file

  1. /*
  2. * File: ftk_canvas_skia.c
  3. * Author: Li XianJing <xianjimli@hotmail.com>
  4. * Brief: skia canvas implemntation.
  5. *
  6. * Copyright (c) 2009 - 2011 Li XianJing <xianjimli@hotmail.com>
  7. *
  8. * Licensed under the Academic Free License version 2.1
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. /*
  25. * History:
  26. * ================================================================
  27. * 2011-04-18 Li XianJing <xianjimli@hotmail.com> created
  28. */
  29. #include "ftk_log.h"
  30. #include "ftk_util.h"
  31. #include "ftk_bitmap.h"
  32. #include "ftk_canvas.h"
  33. #include "SkColor.h"
  34. #include "SkCanvas.h"
  35. #include "ftk_globals.h"
  36. #include "SkImageEncoder.h"
  37. #include "effects/SkPorterDuff.h"
  38. using namespace android;
  39. typedef struct _CanvasSkiaPrivInfo
  40. {
  41. int w;
  42. int h;
  43. SkPaint* paint;
  44. SkCanvas* canvas;
  45. FtkBitmap* bitmap;
  46. }PrivInfo;
  47. static Ret ftk_canvas_skia_sync_gc(FtkCanvas* thiz)
  48. {
  49. int size = 0;
  50. DECL_PRIV(thiz, priv);
  51. FtkColor c = thiz->gc.fg;
  52. #ifdef ANDROID
  53. SkColor color = SkColorSetARGB(c.a, c.r, c.g, c.b);
  54. #else
  55. SkColor color = SkColorSetARGBInline(c.a, c.r, c.g, c.b);
  56. #endif
  57. priv->paint->setColor(color);
  58. if(thiz->gc.font != NULL)
  59. {
  60. char desc[64] = {0};
  61. size = ftk_font_desc_get_size(thiz->gc.font);
  62. priv->paint->setTextSize(SkIntToScalar(size));
  63. }
  64. return RET_OK;
  65. }
  66. static Ret ftk_canvas_skia_set_clip(FtkCanvas* thiz, FtkRegion* clip)
  67. {
  68. SkRegion clipReg;
  69. DECL_PRIV(thiz, priv);
  70. if(clip != NULL)
  71. {
  72. SkIRect rect;
  73. FtkRegion* iter = clip;
  74. while(iter != NULL)
  75. {
  76. rect.set(iter->rect.x, iter->rect.y, iter->rect.x + iter->rect.width, iter->rect.y + iter->rect.height);
  77. clipReg.op(rect, SkRegion::kUnion_Op);
  78. ftk_logd("set_clip: %d %d %d %d\n", iter->rect.x, iter->rect.y, iter->rect.width, iter->rect.height);
  79. iter = iter->next;
  80. }
  81. }
  82. else
  83. {
  84. clipReg.setRect(0, 0, priv->w, priv->h);
  85. ftk_logd("set_clip: %d %d %d %d\n", 0, 0, priv->w, priv->h);
  86. }
  87. priv->canvas->clipRegion(clipReg, SkRegion::kReplace_Op);
  88. return RET_OK;
  89. }
  90. static Ret ftk_canvas_skia_draw_pixels(FtkCanvas* thiz, FtkPoint* points, int nr)
  91. {
  92. int i = 0;
  93. DECL_PRIV(thiz, priv);
  94. for(i = 0; i < nr; i++)
  95. {
  96. priv->canvas->drawPoint(SkIntToScalar(points[i].x), SkIntToScalar(points[i].y), *priv->paint);
  97. }
  98. return RET_OK;
  99. }
  100. static Ret ftk_canvas_skia_draw_line(FtkCanvas* thiz, int x1, int y1, int x2, int y2)
  101. {
  102. DECL_PRIV(thiz, priv);
  103. priv->canvas->drawLine(SkIntToScalar(x1), SkIntToScalar(y1), SkIntToScalar(x2), SkIntToScalar(y2), *priv->paint);
  104. return RET_OK;
  105. }
  106. static Ret ftk_canvas_skia_clear_rect(FtkCanvas* thiz, int x, int y, int w, int h)
  107. {
  108. SkRect rect;
  109. DECL_PRIV(thiz, priv);
  110. rect.iset(x, y, x + w, y + h);
  111. priv->paint->setStyle(SkPaint::kStrokeAndFill_Style);
  112. priv->canvas->drawRect(rect, *priv->paint);
  113. return RET_OK;
  114. }
  115. static Ret ftk_canvas_skia_draw_rect(FtkCanvas* thiz, int x, int y, int w, int h,
  116. int round, int fill)
  117. {
  118. SkRect rect;
  119. Ret ret = RET_FAIL;
  120. DECL_PRIV(thiz, priv);
  121. rect.iset(x, y, x + w, y + h);
  122. if(fill)
  123. {
  124. priv->paint->setStyle(SkPaint::kStrokeAndFill_Style);
  125. }
  126. else
  127. {
  128. priv->paint->setStyle(SkPaint::kStroke_Style);
  129. }
  130. if(round)
  131. {
  132. priv->canvas->drawRoundRect(rect, SkIntToScalar(5), SkIntToScalar(5), *priv->paint);
  133. }
  134. else
  135. {
  136. priv->canvas->drawRect(rect, *priv->paint);
  137. }
  138. priv->paint->setStyle(SkPaint::kStroke_Style);
  139. return ret;
  140. }
  141. static Ret ftk_canvas_skia_draw_bitmap(FtkCanvas* thiz, FtkBitmap* bitmap,
  142. FtkRect* src_r, FtkRect* dst_r, int alpha)
  143. {
  144. SkRect dst;
  145. SkIRect src;
  146. Ret ret = RET_FAIL;
  147. DECL_PRIV(thiz, priv);
  148. return_val_if_fail(thiz != NULL && bitmap != NULL && dst_r != NULL && src_r != NULL, RET_FAIL);
  149. src.set(src_r->x, src_r->y, src_r->x + src_r->width, src_r->y + src_r->height);
  150. dst.iset(dst_r->x, dst_r->y, dst_r->x + dst_r->width, dst_r->y + dst_r->height);
  151. SkBitmap* b = (SkBitmap*)ftk_bitmap_get_native(bitmap);
  152. priv->canvas->drawBitmapRect(*b, &src, dst, priv->paint);
  153. return ret;
  154. }
  155. static Ret ftk_canvas_skia_draw_string(FtkCanvas* thiz, int x, int y,
  156. const char* str, int len, int vcenter)
  157. {
  158. DECL_PRIV(thiz, priv);
  159. if(vcenter)
  160. {
  161. y += ftk_font_desc_get_size(thiz->gc.font)/3;
  162. }
  163. priv->paint->setAntiAlias(true);
  164. priv->canvas->drawText(str, len, SkIntToScalar(x), SkIntToScalar(y), *priv->paint);
  165. priv->paint->setAntiAlias(false);
  166. return RET_OK;
  167. }
  168. static Ret fk_canvas_skia_lock_buffer(FtkCanvas* thiz, FtkBitmap** bitmap)
  169. {
  170. DECL_PRIV(thiz, priv);
  171. return_val_if_fail(bitmap != NULL, RET_FAIL);
  172. *bitmap = priv->bitmap;
  173. return RET_OK;
  174. }
  175. static Ret ftk_canvas_skia_unlock_buffer(FtkCanvas* thiz)
  176. {
  177. return RET_OK;
  178. }
  179. static void ftk_canvas_skia_destroy(FtkCanvas* thiz)
  180. {
  181. DECL_PRIV(thiz, priv);
  182. if(thiz != NULL)
  183. {
  184. priv->canvas->setBitmapDevice(SkBitmap());
  185. ftk_bitmap_unref(priv->bitmap);
  186. delete priv->canvas;
  187. delete priv->paint;
  188. FTK_FREE(thiz);
  189. }
  190. return;
  191. }
  192. static int ftk_canvas_skia_get_char_extent(FtkCanvas* thiz, unsigned short code)
  193. {
  194. int width = 0;
  195. char utf8[8] = {0};
  196. DECL_PRIV(thiz, priv);
  197. SkScalar fwidth = 0;
  198. utf16_to_utf8(&code, 1, utf8, sizeof(utf8));
  199. fwidth = priv->paint->measureText(utf8, strlen(utf8));
  200. width = SkFixedFloor(SkScalarToFixed(fwidth));
  201. return width;
  202. }
  203. static int ftk_canvas_skia_get_str_extent(FtkCanvas* thiz, const char* str, int len)
  204. {
  205. int width = 0;
  206. DECL_PRIV(thiz, priv);
  207. SkScalar fwidth = 0;
  208. fwidth = priv->paint->measureText(str, len);
  209. width = SkFixedFloor(SkScalarToFixed(fwidth));
  210. ftk_logd("%s: %s width=%d\n", __func__, str, width);
  211. return width;
  212. }
  213. static const FtkCanvasVTable g_canvas_skia_vtable=
  214. {
  215. ftk_canvas_skia_sync_gc,
  216. ftk_canvas_skia_set_clip,
  217. ftk_canvas_skia_draw_pixels,
  218. ftk_canvas_skia_draw_line,
  219. ftk_canvas_skia_clear_rect,
  220. ftk_canvas_skia_draw_rect,
  221. ftk_canvas_skia_draw_bitmap,
  222. ftk_canvas_skia_draw_string,
  223. ftk_canvas_skia_get_str_extent,
  224. ftk_canvas_skia_get_char_extent,
  225. fk_canvas_skia_lock_buffer,
  226. ftk_canvas_skia_unlock_buffer,
  227. ftk_canvas_skia_destroy
  228. };
  229. static void destroy_bitmap(void* data)
  230. {
  231. SkBitmap* b = (SkBitmap*)data;
  232. delete b;
  233. return;
  234. }
  235. FtkCanvas* ftk_canvas_create(int w, int h, FtkColor* clear_color)
  236. {
  237. FtkCanvas* thiz = NULL;
  238. return_val_if_fail(w > 0 && h > 0 && clear_color != NULL, NULL);
  239. thiz = (FtkCanvas*)FTK_ZALLOC(sizeof(FtkCanvas) + sizeof(PrivInfo));
  240. if(thiz != NULL)
  241. {
  242. SkBitmap* bitmap = new SkBitmap();
  243. DECL_PRIV(thiz, priv);
  244. thiz->gc.bg = *clear_color;
  245. thiz->gc.fg.a = 0xff;
  246. thiz->gc.fg.r = 0xff - clear_color->r;
  247. thiz->gc.fg.g = 0xff - clear_color->g;
  248. thiz->gc.fg.b = 0xff - clear_color->b;
  249. thiz->gc.mask = FTK_GC_FG | FTK_GC_BG;
  250. thiz->vtable = &g_canvas_skia_vtable;
  251. bitmap->setConfig(SkBitmap::kARGB_8888_Config, w, h, w * 4);
  252. bitmap->allocPixels(NULL);
  253. priv->paint = new SkPaint();
  254. priv->canvas = new SkCanvas();
  255. priv->canvas->setBitmapDevice(*bitmap);
  256. priv->bitmap = ftk_bitmap_create_with_native(bitmap);
  257. priv->w = ftk_bitmap_width(priv->bitmap);
  258. priv->h = ftk_bitmap_height(priv->bitmap);
  259. }
  260. return thiz;
  261. }