/src/ftk_canvas.c

http://ftk.googlecode.com/ · C · 352 lines · 271 code · 51 blank · 30 comment · 59 complexity · 060d491f32dea5d2f790bb23de965463 MD5 · raw file

  1. /*
  2. * File: ftk_canvas.c
  3. * Author: Li XianJing <xianjimli@hotmail.com>
  4. * Brief:
  5. *
  6. * Copyright (c) 2009 - 2010 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. * 2009-10-03 Li XianJing <xianjimli@hotmail.com> created
  28. * 2010-3-16 woodysu<yapo_su@hotmail.com> modified.
  29. */
  30. #include "ftk_log.h"
  31. #include "ftk_util.h"
  32. #include "ftk_bitmap.h"
  33. #include "ftk_canvas.h"
  34. Ret ftk_canvas_reset_gc(FtkCanvas* thiz, FtkGc* gc)
  35. {
  36. return_val_if_fail(thiz != NULL && gc != NULL, RET_FAIL);
  37. ftk_gc_reset(&thiz->gc);
  38. ftk_gc_copy(&thiz->gc, gc);
  39. return ftk_canvas_sync_gc(thiz);
  40. }
  41. Ret ftk_canvas_set_gc(FtkCanvas* thiz, FtkGc* gc)
  42. {
  43. return_val_if_fail(thiz != NULL && gc != NULL, RET_FAIL);
  44. ftk_gc_copy(&thiz->gc, gc);
  45. return ftk_canvas_sync_gc(thiz);
  46. }
  47. FtkGc* ftk_canvas_get_gc(FtkCanvas* thiz)
  48. {
  49. return_val_if_fail(thiz != NULL, NULL);
  50. return &thiz->gc;
  51. }
  52. Ret ftk_canvas_set_clip_rect(FtkCanvas* thiz, FtkRect* rect)
  53. {
  54. if(rect != NULL)
  55. {
  56. FtkRegion region;
  57. region.rect = *rect;
  58. region.next = NULL;
  59. return ftk_canvas_set_clip(thiz, &region);
  60. }
  61. else
  62. {
  63. return ftk_canvas_set_clip(thiz, NULL);
  64. }
  65. }
  66. Ret ftk_canvas_set_clip_region(FtkCanvas* thiz, FtkRegion* region)
  67. {
  68. return ftk_canvas_set_clip(thiz, region);
  69. }
  70. Ret ftk_canvas_draw_vline(FtkCanvas* thiz, int x, int y, int h)
  71. {
  72. return ftk_canvas_draw_line(thiz, x, y, x, y + h);
  73. }
  74. Ret ftk_canvas_draw_hline(FtkCanvas* thiz, int x, int y, int w)
  75. {
  76. return ftk_canvas_draw_line(thiz, x, y, x + w, y);
  77. }
  78. Ret ftk_canvas_draw_bitmap_simple(FtkCanvas* thiz, FtkBitmap* b, int x, int y, int w, int h, int ox, int oy)
  79. {
  80. FtkRect src_r;
  81. FtkRect dst_r;
  82. src_r.x = x;
  83. src_r.y = y;
  84. dst_r.x = ox;
  85. dst_r.y = oy;
  86. src_r.width = dst_r.width = w;
  87. src_r.height = dst_r.height = h;
  88. return ftk_canvas_draw_bitmap(thiz, b, &src_r, &dst_r, 0xff);
  89. }
  90. static Ret ftk_canvas_fill_background_four_corner(FtkCanvas* thiz, int x, int y,
  91. int w, int h, FtkBitmap* bitmap)
  92. {
  93. int i = 0;
  94. int ox = 0;
  95. int oy = 0;
  96. int ow = 0;
  97. int oh = 0;
  98. FtkColor fg = thiz->gc.fg;
  99. int bw = ftk_bitmap_width(bitmap);
  100. int bh = ftk_bitmap_height(bitmap);
  101. int tile_w = FTK_MIN(bw, w) >> 1;
  102. int tile_h = FTK_MIN(bh, h) >> 1;
  103. if ( bw == w && bh == h )
  104. {
  105. ftk_canvas_draw_bitmap_simple(thiz, bitmap, 0, 0, w, h, x, y);
  106. }
  107. else
  108. {
  109. ftk_canvas_draw_bitmap_simple(thiz, bitmap, 0, 0, tile_w, tile_h, x, y);
  110. ftk_canvas_draw_bitmap_simple(thiz, bitmap, bw - tile_w, 0, tile_w, tile_h, x + w - tile_w, y);
  111. ftk_canvas_draw_bitmap_simple(thiz, bitmap, 0, bh - tile_h, tile_w, tile_h, x, y + h - tile_h);
  112. ftk_canvas_draw_bitmap_simple(thiz, bitmap, bw - tile_w, bh - tile_h, tile_w, tile_h, x + w - tile_w, y + h - tile_h);
  113. }
  114. if(bw < w)
  115. {
  116. ox = x + tile_w;
  117. ow = w - 2 * tile_w;
  118. for(i = 0; i < tile_h; i++)
  119. {
  120. thiz->gc.fg = ftk_bitmap_get_pixel(bitmap, tile_w, i);
  121. ftk_canvas_sync_gc(thiz);
  122. ftk_canvas_draw_hline(thiz, ox, y + i, ow);
  123. }
  124. oy = y + tile_h;
  125. oh = h - 2 * tile_h;
  126. thiz->gc.fg = ftk_bitmap_get_pixel(bitmap, tile_w, i);
  127. ftk_canvas_sync_gc(thiz);
  128. ftk_canvas_draw_rect(thiz, ox, oy, ow, oh, 0, 1);
  129. oy = y + h - tile_h;
  130. for(i = 0; i < tile_h; i++)
  131. {
  132. thiz->gc.fg = ftk_bitmap_get_pixel(bitmap, tile_w, (bh - tile_h) + i);
  133. ftk_canvas_sync_gc(thiz);
  134. ftk_canvas_draw_hline(thiz, ox, (oy + i), ow);
  135. }
  136. }
  137. if(bh < h)
  138. {
  139. oy = y + tile_h;
  140. oh = h - 2 * tile_h;
  141. for(i = 0; i < tile_w; i++)
  142. {
  143. thiz->gc.fg = ftk_bitmap_get_pixel(bitmap, i, tile_h);
  144. ftk_canvas_sync_gc(thiz);
  145. ftk_canvas_draw_vline(thiz, x + i, oy, oh);
  146. }
  147. ox = x + w - tile_w;
  148. for(i = 0; i < tile_w; i++)
  149. {
  150. thiz->gc.fg = ftk_bitmap_get_pixel(bitmap, bw - tile_w + i, tile_h);
  151. ftk_canvas_sync_gc(thiz);
  152. ftk_canvas_draw_vline(thiz, ox + i, oy, oh);
  153. }
  154. }
  155. thiz->gc.fg = fg;
  156. ftk_canvas_sync_gc(thiz);
  157. return RET_OK;
  158. }
  159. static Ret ftk_canvas_fill_background_normal(FtkCanvas* thiz, int x, int y,
  160. int w, int h, FtkBitmap* bitmap)
  161. {
  162. int bw = ftk_bitmap_width(bitmap);
  163. int bh = ftk_bitmap_height(bitmap);
  164. w = FTK_MIN(bw, w);
  165. h = FTK_MIN(bh, h);
  166. return ftk_canvas_draw_bitmap_simple(thiz, bitmap, 0, 0, w, h, x, y);
  167. }
  168. static Ret ftk_canvas_fill_background_tile(FtkCanvas* thiz, int x, int y,
  169. int w, int h, FtkBitmap* bitmap)
  170. {
  171. int dx = 0;
  172. int dy = 0;
  173. int bw = ftk_bitmap_width(bitmap);
  174. int bh = ftk_bitmap_height(bitmap);
  175. if(bw > w && bh > h)
  176. {
  177. return ftk_canvas_fill_background_normal(thiz, x, y, w, h, bitmap);
  178. }
  179. for(dy = 0; dy < h; dy += bh)
  180. {
  181. for(dx = 0; dx < w; dx += bw)
  182. {
  183. int draw_w = (dx + bw) < w ? bw : w - dx;
  184. int draw_h = (dy + bh) < h ? bh : h - dy;
  185. ftk_canvas_draw_bitmap_simple(thiz, bitmap, 0, 0, draw_w, draw_h, x + dx, y + dy);
  186. }
  187. }
  188. return RET_OK;
  189. }
  190. static Ret ftk_canvas_fill_background_center(FtkCanvas* thiz, int x, int y, int w, int h, FtkBitmap* bitmap)
  191. {
  192. int bw = ftk_bitmap_width(bitmap);
  193. int bh = ftk_bitmap_height(bitmap);
  194. int ox = bw < w ? x + (w - bw)/2 : x;
  195. int oy = bh < h ? y + (h - bh)/2 : y;
  196. int bx = bw < w ? 0 : (bw - w)/2;
  197. int by = bh < h ? 0 : (bh - h)/2;
  198. w = FTK_MIN(bw, w);
  199. h = FTK_MIN(bh, h);
  200. return ftk_canvas_draw_bitmap_simple(thiz, bitmap, bx, by, w, h, ox, oy);
  201. }
  202. Ret ftk_canvas_draw_bg_image(FtkCanvas* thiz, FtkBitmap* bitmap, FtkBgStyle style,
  203. int x, int y, int w, int h)
  204. {
  205. Ret ret = RET_FAIL;
  206. return_val_if_fail(thiz != NULL && bitmap != NULL, ret);
  207. switch(style)
  208. {
  209. case FTK_BG_TILE:
  210. ret = ftk_canvas_fill_background_tile(thiz, x, y, w, h, bitmap);break;
  211. case FTK_BG_CENTER:
  212. ret = ftk_canvas_fill_background_center(thiz, x, y, w, h, bitmap);break;
  213. case FTK_BG_FOUR_CORNER:
  214. {
  215. int bw = ftk_bitmap_width(bitmap);
  216. int bh = ftk_bitmap_height(bitmap);
  217. if(w <= bw && h <= bh)
  218. {
  219. ret = ftk_canvas_fill_background_center(thiz, x, y, w, h, bitmap);break;
  220. }
  221. else
  222. {
  223. ret = ftk_canvas_fill_background_four_corner(thiz, x, y, w, h, bitmap);
  224. }
  225. break;
  226. }
  227. default:
  228. ret = ftk_canvas_fill_background_normal(thiz, x, y, w, h, bitmap);break;
  229. }
  230. return ret;
  231. }
  232. Ret ftk_canvas_show(FtkCanvas* thiz, FtkDisplay* display, FtkRect* rect, int ox, int oy)
  233. {
  234. FtkBitmap* bitmap = NULL;
  235. ftk_canvas_lock_buffer(thiz, &bitmap);
  236. ftk_display_update_and_notify(display, bitmap, rect, ox, oy);
  237. ftk_canvas_unlock_buffer(thiz);
  238. return RET_OK;
  239. }
  240. const char* ftk_canvas_calc_str_visible_range(FtkCanvas* thiz,
  241. const char* start, int vstart, int vend, int width, int* ret_extent)
  242. {
  243. int extent = 0;
  244. int line_extent = 0;
  245. unsigned short unicode = 0;
  246. const char* iter = NULL;
  247. const char* prev_iter = NULL;
  248. if(vstart >= 0)
  249. {
  250. iter = start + vstart;
  251. prev_iter = iter;
  252. while(width > 0)
  253. {
  254. prev_iter = iter;
  255. unicode = utf8_get_char(iter, &iter);
  256. if(unicode == '\r') continue;
  257. if(unicode == 0 || unicode == 0xffff)
  258. {
  259. break;
  260. }
  261. else if( unicode == '\n')
  262. {
  263. prev_iter = iter;
  264. break;
  265. }
  266. extent = ftk_canvas_get_char_extent(thiz, unicode);
  267. if(extent > width) break;
  268. width -= extent;
  269. line_extent += extent;
  270. prev_iter = iter;
  271. }
  272. if(ret_extent != NULL)
  273. *ret_extent = line_extent;
  274. return prev_iter;
  275. }
  276. else if(vend > 0)
  277. {
  278. iter = start + vend;
  279. prev_iter = iter;
  280. while(width > 0 && iter >= start)
  281. {
  282. prev_iter = iter;
  283. if(iter <= start) break;
  284. unicode = utf8_get_prev_char(iter, &iter);
  285. if(unicode == '\r') continue;
  286. if(unicode == 0 || unicode == 0xffff || unicode == '\n')
  287. {
  288. // prev_iter = iter;
  289. break;
  290. }
  291. extent = ftk_canvas_get_char_extent(thiz, unicode);
  292. if(extent > width) break;
  293. width -= extent;
  294. line_extent += extent;
  295. }
  296. if(ret_extent != NULL)
  297. *ret_extent = line_extent;
  298. return prev_iter;
  299. }
  300. return start;
  301. }