dc_blend.c 71 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715
  1. /*
  2. * File : dc_blend.c
  3. * This file is part of RT-Thread GUI Engine
  4. * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2013-10-04 Bernard porting SDL software render to RT-Thread GUI
  23. * 2014-05-06 Bernard Add the SDL2_gfx copyright for aa_ecllipse/
  24. * thick_line etc.
  25. */
  26. /*
  27. Simple DirectMedia Layer
  28. Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
  29. This software is provided 'as-is', without any express or implied
  30. warranty. In no event will the authors be held liable for any damages
  31. arising from the use of this software.
  32. Permission is granted to anyone to use this software for any purpose,
  33. including commercial applications, and to alter it and redistribute it
  34. freely, subject to the following restrictions:
  35. 1. The origin of this software must not be misrepresented; you must not
  36. claim that you wrote the original software. If you use this software
  37. in a product, an acknowledgment in the product documentation would be
  38. appreciated but is not required.
  39. 2. Altered source versions must be plainly marked as such, and must not be
  40. misrepresented as being the original software.
  41. 3. This notice may not be removed or altered from any source distribution.
  42. */
  43. /*
  44. SDL2_gfx: graphics primitives for SDL
  45. Copyright (C) 2012 Andreas Schiffler
  46. This software is provided 'as-is', without any express or implied
  47. warranty. In no event will the authors be held liable for any damages
  48. arising from the use of this software.
  49. Permission is granted to anyone to use this software for any purpose,
  50. including commercial applications, and to alter it and redistribute it
  51. freely, subject to the following restrictions:
  52. 1. The origin of this software must not be misrepresented; you must not
  53. claim that you wrote the original software. If you use this software
  54. in a product, an acknowledgment in the product documentation would be
  55. appreciated but is not required.
  56. 2. Altered source versions must be plainly marked as such, and must not be
  57. misrepresented as being the original software.
  58. 3. This notice may not be removed or altered from any source
  59. distribution.
  60. Andreas Schiffler -- aschiffler at ferzkopp dot net
  61. */
  62. #include <rtgui/dc.h>
  63. #include <rtgui/dc_draw.h>
  64. #include <rtgui/color.h>
  65. #include <string.h>
  66. #include <math.h>
  67. #include <stdlib.h>
  68. #define hw_driver (rtgui_graphic_driver_get_default())
  69. #define _int_swap(x, y) do {x ^= y; y ^= x; x ^= y;} while (0)
  70. rt_inline rt_uint8_t _dc_get_bits_per_pixel(struct rtgui_dc* dc)
  71. {
  72. rt_uint8_t bits_per_pixel = 0;
  73. if (dc->type == RTGUI_DC_HW || dc->type == RTGUI_DC_CLIENT)
  74. bits_per_pixel = hw_driver->bits_per_pixel;
  75. else if (dc->type == RTGUI_DC_BUFFER)
  76. {
  77. struct rtgui_dc_buffer *buffer = (struct rtgui_dc_buffer*)dc;
  78. bits_per_pixel = rtgui_color_get_bits(buffer->pixel_format);
  79. }
  80. return bits_per_pixel;
  81. }
  82. rt_inline rt_uint16_t _dc_get_pitch(struct rtgui_dc* dc)
  83. {
  84. rt_uint16_t pitch = 0;
  85. if (dc->type == RTGUI_DC_HW || dc->type == RTGUI_DC_CLIENT)
  86. pitch = hw_driver->pitch;
  87. else if (dc->type == RTGUI_DC_BUFFER)
  88. {
  89. struct rtgui_dc_buffer *dc_buffer;
  90. dc_buffer = (struct rtgui_dc_buffer*)dc;
  91. pitch = dc_buffer->pitch;
  92. }
  93. return pitch;
  94. }
  95. rt_inline rt_uint8_t* _dc_get_pixel(struct rtgui_dc* dc, int x, int y)
  96. {
  97. rt_uint8_t *pixel = RT_NULL;
  98. if ((dc->type == RTGUI_DC_HW) || (dc->type == RTGUI_DC_CLIENT))
  99. {
  100. pixel = (rt_uint8_t*)(hw_driver->framebuffer);
  101. if (pixel == RT_NULL) return RT_NULL;
  102. pixel = pixel + y * hw_driver->pitch + x * (_UI_BITBYTES(hw_driver->bits_per_pixel));
  103. }
  104. else if (dc->type == RTGUI_DC_BUFFER)
  105. {
  106. struct rtgui_dc_buffer *dc_buffer;
  107. dc_buffer = (struct rtgui_dc_buffer*)dc;
  108. pixel = dc_buffer->pixel + y * dc_buffer->pitch +
  109. x * rtgui_color_get_bpp(dc_buffer->pixel_format);
  110. }
  111. return pixel;
  112. }
  113. /* Use the Cohen-Sutherland algorithm for line clipping */
  114. #define CODE_BOTTOM 1
  115. #define CODE_TOP 2
  116. #define CODE_LEFT 4
  117. #define CODE_RIGHT 8
  118. static int ComputeOutCode(const rtgui_rect_t * rect, int x, int y)
  119. {
  120. int code = 0;
  121. if (y < rect->y1)
  122. {
  123. code |= CODE_TOP;
  124. }
  125. else if (y > rect->y2)
  126. {
  127. code |= CODE_BOTTOM;
  128. }
  129. if (x < rect->x1)
  130. {
  131. code |= CODE_LEFT;
  132. }
  133. else if (x > rect->x2)
  134. {
  135. code |= CODE_RIGHT;
  136. }
  137. return code;
  138. }
  139. static rt_bool_t _intersect_rect_line(const rtgui_rect_t* rect,
  140. int *X1, int *Y1,
  141. int *X2, int *Y2)
  142. {
  143. int x = 0;
  144. int y = 0;
  145. int x1, y1;
  146. int x2, y2;
  147. int rectx1;
  148. int recty1;
  149. int rectx2;
  150. int recty2;
  151. int outcode1, outcode2;
  152. x1 = *X1;
  153. y1 = *Y1;
  154. x2 = *X2;
  155. y2 = *Y2;
  156. rectx1 = rect->x1;
  157. recty1 = rect->y1;
  158. rectx2 = rect->x2 - 1;
  159. recty2 = rect->y2 - 1;
  160. /* Check to see if entire line is inside rect */
  161. if (x1 >= rectx1 && x1 <= rectx2 && x2 >= rectx1 && x2 <= rectx2 &&
  162. y1 >= recty1 && y1 <= recty2 && y2 >= recty1 && y2 <= recty2)
  163. {
  164. return RT_TRUE;
  165. }
  166. /* Check to see if entire line is to one side of rect */
  167. if ((x1 < rectx1 && x2 < rectx1) || (x1 > rectx2 && x2 > rectx2) ||
  168. (y1 < recty1 && y2 < recty1) || (y1 > recty2 && y2 > recty2))
  169. {
  170. return RT_FALSE;
  171. }
  172. if (y1 == y2)
  173. {
  174. /* Horizontal line, easy to clip */
  175. if (x1 < rectx1)
  176. {
  177. *X1 = rectx1;
  178. }
  179. else if (x1 > rectx2)
  180. {
  181. *X1 = rectx2;
  182. }
  183. if (x2 < rectx1)
  184. {
  185. *X2 = rectx1;
  186. }
  187. else if (x2 > rectx2)
  188. {
  189. *X2 = rectx2;
  190. }
  191. return RT_TRUE;
  192. }
  193. if (x1 == x2)
  194. {
  195. /* Vertical line, easy to clip */
  196. if (y1 < recty1)
  197. {
  198. *Y1 = recty1;
  199. }
  200. else if (y1 > recty2)
  201. {
  202. *Y1 = recty2;
  203. }
  204. if (y2 < recty1)
  205. {
  206. *Y2 = recty1;
  207. }
  208. else if (y2 > recty2)
  209. {
  210. *Y2 = recty2;
  211. }
  212. return RT_TRUE;
  213. }
  214. /* More complicated Cohen-Sutherland algorithm */
  215. outcode1 = ComputeOutCode(rect, x1, y1);
  216. outcode2 = ComputeOutCode(rect, x2, y2);
  217. while (outcode1 || outcode2)
  218. {
  219. if (outcode1 & outcode2)
  220. {
  221. return RT_FALSE;
  222. }
  223. if (outcode1)
  224. {
  225. if (outcode1 & CODE_TOP)
  226. {
  227. y = recty1;
  228. x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
  229. }
  230. else if (outcode1 & CODE_BOTTOM)
  231. {
  232. y = recty2;
  233. x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
  234. }
  235. else if (outcode1 & CODE_LEFT)
  236. {
  237. x = rectx1;
  238. y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
  239. }
  240. else if (outcode1 & CODE_RIGHT)
  241. {
  242. x = rectx2;
  243. y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
  244. }
  245. x1 = x;
  246. y1 = y;
  247. outcode1 = ComputeOutCode(rect, x, y);
  248. }
  249. else
  250. {
  251. if (outcode2 & CODE_TOP)
  252. {
  253. y = recty1;
  254. x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
  255. }
  256. else if (outcode2 & CODE_BOTTOM)
  257. {
  258. y = recty2;
  259. x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
  260. }
  261. else if (outcode2 & CODE_LEFT)
  262. {
  263. x = rectx1;
  264. y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
  265. }
  266. else if (outcode2 & CODE_RIGHT)
  267. {
  268. x = rectx2;
  269. y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
  270. }
  271. x2 = x;
  272. y2 = y;
  273. outcode2 = ComputeOutCode(rect, x, y);
  274. }
  275. }
  276. *X1 = x1;
  277. *Y1 = y1;
  278. *X2 = x2;
  279. *Y2 = y2;
  280. return RT_TRUE;
  281. }
  282. static void
  283. _dc_draw_line1(struct rtgui_dc * dst, int x1, int y1, int x2, int y2, rtgui_color_t color,
  284. rt_bool_t draw_end)
  285. {
  286. if (y1 == y2)
  287. {
  288. int length;
  289. rt_uint8_t *pixel;
  290. if (x1 <= x2)
  291. {
  292. pixel = (rt_uint8_t *)_dc_get_pixel(dst, x1, y1);
  293. length = draw_end ? (x2-x1+1) : (x2-x1);
  294. }
  295. else
  296. {
  297. pixel = (rt_uint8_t *)_dc_get_pixel(dst, x2, y1);
  298. if (!draw_end)
  299. {
  300. ++pixel;
  301. }
  302. length = draw_end ? (x1-x2+1) : (x1-x2);
  303. }
  304. rt_memset(pixel, color, length);
  305. }
  306. else if (x1 == x2)
  307. {
  308. VLINE(rt_uint8_t, DRAW_FASTSETPIXEL1, draw_end);
  309. }
  310. else if (ABS(x1 - x2) == ABS(y1 - y2))
  311. {
  312. DLINE(rt_uint8_t, DRAW_FASTSETPIXEL1, draw_end);
  313. }
  314. else
  315. {
  316. BLINE(x1, y1, x2, y2, DRAW_FASTSETPIXELXY1, draw_end);
  317. }
  318. }
  319. static void
  320. _dc_draw_line2(struct rtgui_dc * dst, int x1, int y1, int x2, int y2, rtgui_color_t c,
  321. rt_bool_t draw_end)
  322. {
  323. rt_uint16_t color;
  324. if (rtgui_dc_get_pixel_format(dst) == RTGRAPHIC_PIXEL_FORMAT_RGB565)
  325. color = rtgui_color_to_565(c);
  326. else
  327. color = rtgui_color_to_565p(c);
  328. if (y1 == y2)
  329. {
  330. HLINE(rt_uint16_t, DRAW_FASTSETPIXEL2, draw_end);
  331. }
  332. else if (x1 == x2)
  333. {
  334. VLINE(rt_uint16_t, DRAW_FASTSETPIXEL2, draw_end);
  335. }
  336. else if (ABS(x1 - x2) == ABS(y1 - y2))
  337. {
  338. DLINE(rt_uint16_t, DRAW_FASTSETPIXEL2, draw_end);
  339. }
  340. else
  341. {
  342. rt_uint8_t _r, _g, _b, _a;
  343. _r = RTGUI_RGB_R(c);
  344. _g = RTGUI_RGB_G(c);
  345. _b = RTGUI_RGB_B(c);
  346. _a = RTGUI_RGB_A(c);
  347. if (rtgui_dc_get_pixel_format(dst) == RTGRAPHIC_PIXEL_FORMAT_RGB565)
  348. {
  349. AALINE(x1, y1, x2, y2,
  350. DRAW_FASTSETPIXELXY2, DRAW_SETPIXELXY_BLEND_RGB565,
  351. draw_end);
  352. }
  353. else if (rtgui_dc_get_pixel_format(dst) == RTGRAPHIC_PIXEL_FORMAT_BGR565)
  354. {
  355. AALINE(x1, y1, x2, y2,
  356. DRAW_FASTSETPIXELXY2, DRAW_SETPIXELXY_BLEND_BGR565,
  357. draw_end);
  358. }
  359. }
  360. }
  361. static void
  362. _dc_draw_line4(struct rtgui_dc * dst, int x1, int y1, int x2, int y2, rtgui_color_t color,
  363. rt_bool_t draw_end)
  364. {
  365. if (y1 == y2)
  366. {
  367. HLINE(rt_uint32_t, DRAW_FASTSETPIXEL4, draw_end);
  368. }
  369. else if (x1 == x2)
  370. {
  371. VLINE(rt_uint32_t, DRAW_FASTSETPIXEL4, draw_end);
  372. }
  373. else if (ABS(x1 - x2) == ABS(y1 - y2))
  374. {
  375. DLINE(rt_uint32_t, DRAW_FASTSETPIXEL4, draw_end);
  376. }
  377. else
  378. {
  379. rt_uint8_t _r, _g, _b, _a;
  380. _r = RTGUI_RGB_R(color);
  381. _g = RTGUI_RGB_G(color);
  382. _b = RTGUI_RGB_B(color);
  383. _a = RTGUI_RGB_A(color);
  384. if (rtgui_dc_get_pixel_format(dst) == RTGRAPHIC_PIXEL_FORMAT_RGB888)
  385. {
  386. AALINE(x1, y1, x2, y2,
  387. DRAW_FASTSETPIXELXY4, DRAW_SETPIXELXY_BLEND_RGB888,
  388. draw_end);
  389. }
  390. else if (rtgui_dc_get_pixel_format(dst) == RTGRAPHIC_PIXEL_FORMAT_ARGB888)
  391. {
  392. AALINE(x1, y1, x2, y2,
  393. DRAW_FASTSETPIXELXY4, DRAW_SETPIXELXY_BLEND_ARGB8888,
  394. draw_end);
  395. }
  396. }
  397. }
  398. typedef void (*DrawLineFunc) (struct rtgui_dc * dst,
  399. int x1, int y1, int x2, int y2,
  400. rtgui_color_t color, rt_bool_t draw_end);
  401. static DrawLineFunc
  402. _dc_calc_draw_line_func(int bpp)
  403. {
  404. switch (bpp)
  405. {
  406. case 1:
  407. return _dc_draw_line1;
  408. case 2:
  409. return _dc_draw_line2;
  410. case 4:
  411. return _dc_draw_line4;
  412. }
  413. return NULL;
  414. }
  415. static void _do_draw_line(struct rtgui_dc * dst,
  416. rtgui_color_t color,
  417. int x1, int y1,
  418. int x2, int y2,
  419. rt_bool_t draw_end)
  420. {
  421. int bpp;
  422. DrawLineFunc func;
  423. bpp = _dc_get_bits_per_pixel(dst);
  424. if (bpp < 8)
  425. return;
  426. func = _dc_calc_draw_line_func(bpp/8);
  427. if (!func)
  428. {
  429. rt_kprintf("dc_draw_line(): Unsupported pixel format\n");
  430. return;
  431. }
  432. /* perform clip */
  433. if (dst->type == RTGUI_DC_CLIENT)
  434. {
  435. rtgui_widget_t *owner;
  436. /* get owner */
  437. owner = RTGUI_CONTAINER_OF(dst, struct rtgui_widget, dc_type);
  438. x1 = x1 + owner->extent.x1;
  439. x2 = x2 + owner->extent.x1;
  440. y1 = y1 + owner->extent.y1;
  441. y2 = y2 + owner->extent.y1;
  442. if (owner->clip.data == RT_NULL)
  443. {
  444. rtgui_rect_t *prect;
  445. /* no clip */
  446. prect = &(owner->clip.extents);
  447. /* calculate line intersect */
  448. if (_intersect_rect_line(prect, &x1, &y1, &x2, &y2) == RT_FALSE)
  449. return;
  450. /* draw line */
  451. func(dst, x1, y1, x2, y2, color, draw_end);
  452. }
  453. else
  454. {
  455. register rt_base_t index;
  456. for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++)
  457. {
  458. rtgui_rect_t *prect;
  459. int draw_x1, draw_x2;
  460. int draw_y1, draw_y2;
  461. prect = ((rtgui_rect_t *)(owner->clip.data + index + 1));
  462. draw_x1 = x1;
  463. draw_x2 = x2;
  464. draw_y1 = y1;
  465. draw_y2 = y2;
  466. /* calculate line intersect */
  467. if (_intersect_rect_line(prect, &draw_x1, &draw_y1, &draw_x2, &draw_y2) == RT_FALSE)
  468. continue;
  469. /* draw line */
  470. func(dst, draw_x1, draw_y1, draw_x2, draw_y2, color, draw_end);
  471. }
  472. }
  473. }
  474. else
  475. {
  476. if (dst->type == RTGUI_DC_HW)
  477. {
  478. rtgui_widget_t *owner;
  479. rtgui_rect_t *prect;
  480. /* no clip */
  481. struct rtgui_dc_hw *dc_hw = (struct rtgui_dc_hw*)dst;
  482. owner = dc_hw->owner;
  483. x1 = x1 + owner->extent.x1;
  484. x2 = x2 + owner->extent.x1;
  485. y1 = y1 + owner->extent.y1;
  486. y2 = y2 + owner->extent.y1;
  487. prect = &(owner->clip.extents);
  488. if (_intersect_rect_line(prect, &x1, &y1, &x2, &y2) == RT_FALSE)
  489. return;
  490. }
  491. else if (dst->type == RTGUI_DC_BUFFER)
  492. {
  493. rtgui_rect_t rect;
  494. struct rtgui_dc_buffer *pbf = (struct rtgui_dc_buffer *)dst;
  495. rect.x1 = rect.y1 = 0;
  496. rect.x2 = pbf->width;
  497. rect.y2 = pbf->height;
  498. if (_intersect_rect_line(&rect, &x1, &y1, &x2, &y2) == RT_FALSE)
  499. return;
  500. }
  501. func(dst, x1, y1, x2, y2, color, draw_end);
  502. }
  503. }
  504. void rtgui_dc_draw_aa_line(struct rtgui_dc * dst, int x1, int y1, int x2, int y2)
  505. {
  506. rtgui_color_t color;
  507. RT_ASSERT(dst != RT_NULL);
  508. if (!rtgui_dc_get_visible(dst))
  509. return;
  510. /* we do not support pixel DC */
  511. if (_dc_get_pixel(dst, 0, 0) == RT_NULL)
  512. return;
  513. color = rtgui_dc_get_gc(dst)->foreground;
  514. _do_draw_line(dst, color, x1, y1, x2, y2, RT_FALSE);
  515. }
  516. RTM_EXPORT(rtgui_dc_draw_aa_line);
  517. void rtgui_dc_draw_aa_lines(struct rtgui_dc * dst, const struct rtgui_point * points, int count)
  518. {
  519. int i;
  520. int x1, y1;
  521. int x2, y2;
  522. rtgui_color_t color;
  523. RT_ASSERT(dst);
  524. if (!rtgui_dc_get_visible(dst))
  525. return;
  526. /* we do not support pixel DC */
  527. if (_dc_get_pixel(dst, 0, 0) == RT_NULL)
  528. return;
  529. color = rtgui_dc_get_gc(dst)->foreground;
  530. for (i = 1; i < count; ++i)
  531. {
  532. rt_bool_t draw_end;
  533. x1 = points[i-1].x;
  534. y1 = points[i-1].y;
  535. x2 = points[i].x;
  536. y2 = points[i].y;
  537. /* Draw the end if it was clipped */
  538. draw_end = (x2 != points[i].x || y2 != points[i].y);
  539. _do_draw_line(dst, color, x1, y1, x2, y2, draw_end);
  540. }
  541. if (points[0].x != points[count-1].x || points[0].y != points[count-1].y)
  542. {
  543. rtgui_dc_draw_point(dst, points[count-1].x, points[count-1].y);
  544. }
  545. return ;
  546. }
  547. static int
  548. _dc_blend_point_rgb565(struct rtgui_dc * dst, int x, int y, enum RTGUI_BLENDMODE blendMode, rt_uint8_t r,
  549. rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
  550. {
  551. unsigned inva = 0xff - a;
  552. switch (blendMode)
  553. {
  554. case RTGUI_BLENDMODE_BLEND:
  555. DRAW_SETPIXELXY_BLEND_RGB565(x, y);
  556. break;
  557. case RTGUI_BLENDMODE_ADD:
  558. DRAW_SETPIXELXY_ADD_RGB565(x, y);
  559. break;
  560. case RTGUI_BLENDMODE_MOD:
  561. DRAW_SETPIXELXY_MOD_RGB565(x, y);
  562. break;
  563. default:
  564. DRAW_SETPIXELXY_RGB565(x, y);
  565. break;
  566. }
  567. return 0;
  568. }
  569. static int
  570. _dc_blend_point_bgr565(struct rtgui_dc * dst, int x, int y, enum RTGUI_BLENDMODE blendMode, rt_uint8_t r,
  571. rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
  572. {
  573. unsigned inva = 0xff - a;
  574. switch (blendMode)
  575. {
  576. case RTGUI_BLENDMODE_BLEND:
  577. DRAW_SETPIXELXY_BLEND_BGR565(x, y);
  578. break;
  579. case RTGUI_BLENDMODE_ADD:
  580. DRAW_SETPIXELXY_ADD_BGR565(x, y);
  581. break;
  582. case RTGUI_BLENDMODE_MOD:
  583. DRAW_SETPIXELXY_MOD_BGR565(x, y);
  584. break;
  585. default:
  586. DRAW_SETPIXELXY_BGR565(x, y);
  587. break;
  588. }
  589. return 0;
  590. }
  591. static int
  592. _dc_blend_point_rgb888(struct rtgui_dc * dst, int x, int y, enum RTGUI_BLENDMODE blendMode, rt_uint8_t r,
  593. rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
  594. {
  595. unsigned inva = 0xff - a;
  596. switch (blendMode)
  597. {
  598. case RTGUI_BLENDMODE_BLEND:
  599. DRAW_SETPIXELXY_BLEND_RGB888(x, y);
  600. break;
  601. case RTGUI_BLENDMODE_ADD:
  602. DRAW_SETPIXELXY_ADD_RGB888(x, y);
  603. break;
  604. case RTGUI_BLENDMODE_MOD:
  605. DRAW_SETPIXELXY_MOD_RGB888(x, y);
  606. break;
  607. default:
  608. DRAW_SETPIXELXY_RGB888(x, y);
  609. break;
  610. }
  611. return 0;
  612. }
  613. static int
  614. _dc_blend_point_argb8888(struct rtgui_dc * dst, int x, int y, enum RTGUI_BLENDMODE blendMode,
  615. rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
  616. {
  617. unsigned inva = 0xff - a;
  618. switch (blendMode)
  619. {
  620. case RTGUI_BLENDMODE_BLEND:
  621. DRAW_SETPIXELXY_BLEND_ARGB8888(x, y);
  622. break;
  623. case RTGUI_BLENDMODE_ADD:
  624. DRAW_SETPIXELXY_ADD_ARGB8888(x, y);
  625. break;
  626. case RTGUI_BLENDMODE_MOD:
  627. DRAW_SETPIXELXY_MOD_ARGB8888(x, y);
  628. break;
  629. default:
  630. DRAW_SETPIXELXY_ARGB8888(x, y);
  631. break;
  632. }
  633. return 0;
  634. }
  635. void
  636. rtgui_dc_blend_point(struct rtgui_dc * dst, int x, int y, enum RTGUI_BLENDMODE blendMode, rt_uint8_t r,
  637. rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
  638. {
  639. RT_ASSERT(dst != RT_NULL);
  640. /* Negative coordinates are always invisible. */
  641. if (x < 0 || y < 0)
  642. return;
  643. if (!rtgui_dc_get_visible(dst)) return;
  644. /* we do not support pixel DC */
  645. if (_dc_get_pixel(dst, 0, 0) == RT_NULL) return;
  646. /* Perform clipping */
  647. if (dst->type == RTGUI_DC_CLIENT)
  648. {
  649. rtgui_widget_t *owner;
  650. rtgui_rect_t rect;
  651. /* get owner */
  652. owner = RTGUI_CONTAINER_OF(dst, struct rtgui_widget, dc_type);
  653. x = x + owner->extent.x1;
  654. y = y + owner->extent.y1;
  655. if (rtgui_region_contains_point(&(owner->clip), x, y, &rect) != RT_EOK)
  656. return ;
  657. }
  658. else if (dst->type == RTGUI_DC_HW)
  659. {
  660. struct rtgui_dc_hw *dc = (struct rtgui_dc_hw *) dst;
  661. x = x + dc->owner->extent.x1;
  662. y = y + dc->owner->extent.y1;
  663. if (x >= dc->owner->extent.x2)
  664. return;
  665. if (y >= dc->owner->extent.y2)
  666. return;
  667. }
  668. else if (dst->type == RTGUI_DC_BUFFER)
  669. {
  670. struct rtgui_dc_buffer *dc = (struct rtgui_dc_buffer *) dst;
  671. if (x >= dc->width || y >= dc->height)
  672. return;
  673. }
  674. if (blendMode == RTGUI_BLENDMODE_BLEND || blendMode == RTGUI_BLENDMODE_ADD)
  675. {
  676. r = DRAW_MUL(r, a);
  677. g = DRAW_MUL(g, a);
  678. b = DRAW_MUL(b, a);
  679. }
  680. switch (rtgui_dc_get_pixel_format(dst))
  681. {
  682. case RTGRAPHIC_PIXEL_FORMAT_RGB565:
  683. _dc_blend_point_rgb565(dst, x, y, blendMode, r, g, b, a);
  684. break;
  685. case RTGRAPHIC_PIXEL_FORMAT_BGR565:
  686. _dc_blend_point_bgr565(dst, x, y, blendMode, r, g, b, a);
  687. break;
  688. case RTGRAPHIC_PIXEL_FORMAT_RGB888:
  689. _dc_blend_point_rgb888(dst, x, y, blendMode, r, g, b, a);
  690. break;
  691. case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
  692. _dc_blend_point_argb8888(dst, x, y, blendMode, r, g, b, a);
  693. break;
  694. default:
  695. break;
  696. }
  697. }
  698. RTM_EXPORT(rtgui_dc_blend_point);
  699. void
  700. rtgui_dc_blend_points(struct rtgui_dc *dst, const rtgui_point_t *points, int count,
  701. enum RTGUI_BLENDMODE blendMode, rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
  702. {
  703. int i;
  704. int x, y;
  705. int (*func)(struct rtgui_dc * dst, int x, int y,
  706. enum RTGUI_BLENDMODE blendMode, rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a) = NULL;
  707. RT_ASSERT(dst != RT_NULL);
  708. if (!rtgui_dc_get_visible(dst)) return;
  709. /* we do not support pixel DC */
  710. if (_dc_get_pixel(dst, 0, 0) == RT_NULL) return;
  711. if (blendMode == RTGUI_BLENDMODE_BLEND || blendMode == RTGUI_BLENDMODE_ADD)
  712. {
  713. r = DRAW_MUL(r, a);
  714. g = DRAW_MUL(g, a);
  715. b = DRAW_MUL(b, a);
  716. }
  717. /* FIXME: Does this function pointer slow things down significantly? */
  718. switch (rtgui_dc_get_pixel_format(dst))
  719. {
  720. case RTGRAPHIC_PIXEL_FORMAT_RGB565:
  721. func = _dc_blend_point_rgb565;
  722. break;
  723. case RTGRAPHIC_PIXEL_FORMAT_RGB888:
  724. func = _dc_blend_point_rgb888;
  725. break;
  726. case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
  727. func = _dc_blend_point_argb8888;
  728. default:
  729. return;
  730. }
  731. /* get owner */
  732. if (dst->type == RTGUI_DC_CLIENT)
  733. {
  734. rtgui_widget_t *owner;
  735. rtgui_rect_t rect;
  736. owner = RTGUI_CONTAINER_OF(dst, struct rtgui_widget, dc_type);
  737. for (i = 0; i < count; ++i)
  738. {
  739. x = points[i].x;
  740. y = points[i].y;
  741. /* Perform clipping */
  742. x = x + owner->extent.x1;
  743. y = y + owner->extent.y1;
  744. if (rtgui_region_contains_point(&(owner->clip), x, y, &rect) != RT_EOK)
  745. continue;
  746. func(dst, x, y, blendMode, r, g, b, a);
  747. }
  748. }
  749. else if (dst->type == RTGUI_DC_HW)
  750. {
  751. struct rtgui_dc_hw *dc = (struct rtgui_dc_hw *) dst;
  752. for (i = 0; i < count; ++i)
  753. {
  754. x = points[i].x;
  755. y = points[i].y;
  756. x = x + dc->owner->extent.x1;
  757. y = y + dc->owner->extent.y1;
  758. if (x > dc->owner->extent.x2) return;
  759. if (y > dc->owner->extent.y2) return;
  760. func(dst, x, y, blendMode, r, g, b, a);
  761. }
  762. }
  763. else
  764. {
  765. for (i = 0; i < count; ++i)
  766. {
  767. x = points[i].x;
  768. y = points[i].y;
  769. func(dst, x, y, blendMode, r, g, b, a);
  770. }
  771. }
  772. }
  773. RTM_EXPORT(rtgui_dc_blend_points);
  774. static void
  775. _dc_blend_line_rgb565(struct rtgui_dc * dst, int x1, int y1, int x2, int y2,
  776. enum RTGUI_BLENDMODE blendMode, rt_uint8_t _r, rt_uint8_t _g, rt_uint8_t _b, rt_uint8_t _a,
  777. rt_bool_t draw_end)
  778. {
  779. unsigned r, g, b, a, inva;
  780. if (blendMode == RTGUI_BLENDMODE_BLEND || blendMode == RTGUI_BLENDMODE_ADD)
  781. {
  782. r = DRAW_MUL(_r, _a);
  783. g = DRAW_MUL(_g, _a);
  784. b = DRAW_MUL(_b, _a);
  785. a = _a;
  786. }
  787. else
  788. {
  789. r = _r;
  790. g = _g;
  791. b = _b;
  792. a = _a;
  793. }
  794. inva = (a ^ 0xff);
  795. if (y1 == y2)
  796. {
  797. switch (blendMode)
  798. {
  799. case RTGUI_BLENDMODE_BLEND:
  800. HLINE(rt_uint16_t, DRAW_SETPIXEL_BLEND_RGB565, draw_end);
  801. break;
  802. case RTGUI_BLENDMODE_ADD:
  803. HLINE(rt_uint16_t, DRAW_SETPIXEL_ADD_RGB565, draw_end);
  804. break;
  805. case RTGUI_BLENDMODE_MOD:
  806. HLINE(rt_uint16_t, DRAW_SETPIXEL_MOD_RGB565, draw_end);
  807. break;
  808. default:
  809. HLINE(rt_uint16_t, DRAW_SETPIXEL_RGB565, draw_end);
  810. break;
  811. }
  812. }
  813. else if (x1 == x2)
  814. {
  815. switch (blendMode)
  816. {
  817. case RTGUI_BLENDMODE_BLEND:
  818. VLINE(rt_uint16_t, DRAW_SETPIXEL_BLEND_RGB565, draw_end);
  819. break;
  820. case RTGUI_BLENDMODE_ADD:
  821. VLINE(rt_uint16_t, DRAW_SETPIXEL_ADD_RGB565, draw_end);
  822. break;
  823. case RTGUI_BLENDMODE_MOD:
  824. VLINE(rt_uint16_t, DRAW_SETPIXEL_MOD_RGB565, draw_end);
  825. break;
  826. default:
  827. VLINE(rt_uint16_t, DRAW_SETPIXEL_RGB565, draw_end);
  828. break;
  829. }
  830. }
  831. else if (ABS(x1 - x2) == ABS(y1 - y2))
  832. {
  833. switch (blendMode)
  834. {
  835. case RTGUI_BLENDMODE_BLEND:
  836. DLINE(rt_uint16_t, DRAW_SETPIXEL_BLEND_RGB565, draw_end);
  837. break;
  838. case RTGUI_BLENDMODE_ADD:
  839. DLINE(rt_uint16_t, DRAW_SETPIXEL_ADD_RGB565, draw_end);
  840. break;
  841. case RTGUI_BLENDMODE_MOD:
  842. DLINE(rt_uint16_t, DRAW_SETPIXEL_MOD_RGB565, draw_end);
  843. break;
  844. default:
  845. DLINE(rt_uint16_t, DRAW_SETPIXEL_RGB565, draw_end);
  846. break;
  847. }
  848. }
  849. else
  850. {
  851. switch (blendMode)
  852. {
  853. case RTGUI_BLENDMODE_BLEND:
  854. AALINE(x1, y1, x2, y2,
  855. DRAW_SETPIXELXY_BLEND_RGB565, DRAW_SETPIXELXY_BLEND_RGB565,
  856. draw_end);
  857. break;
  858. case RTGUI_BLENDMODE_ADD:
  859. AALINE(x1, y1, x2, y2,
  860. DRAW_SETPIXELXY_ADD_RGB565, DRAW_SETPIXELXY_ADD_RGB565,
  861. draw_end);
  862. break;
  863. case RTGUI_BLENDMODE_MOD:
  864. AALINE(x1, y1, x2, y2,
  865. DRAW_SETPIXELXY_MOD_RGB565, DRAW_SETPIXELXY_MOD_RGB565,
  866. draw_end);
  867. break;
  868. default:
  869. AALINE(x1, y1, x2, y2,
  870. DRAW_SETPIXELXY_RGB565, DRAW_SETPIXELXY_BLEND_RGB565,
  871. draw_end);
  872. break;
  873. }
  874. }
  875. }
  876. static void
  877. _dc_blend_line_bgr565(struct rtgui_dc * dst, int x1, int y1, int x2, int y2,
  878. enum RTGUI_BLENDMODE blendMode, rt_uint8_t _r, rt_uint8_t _g, rt_uint8_t _b, rt_uint8_t _a,
  879. rt_bool_t draw_end)
  880. {
  881. unsigned r, g, b, a, inva;
  882. if (blendMode == RTGUI_BLENDMODE_BLEND || blendMode == RTGUI_BLENDMODE_ADD)
  883. {
  884. r = DRAW_MUL(_r, _a);
  885. g = DRAW_MUL(_g, _a);
  886. b = DRAW_MUL(_b, _a);
  887. a = _a;
  888. }
  889. else
  890. {
  891. r = _r;
  892. g = _g;
  893. b = _b;
  894. a = _a;
  895. }
  896. inva = (a ^ 0xff);
  897. if (y1 == y2)
  898. {
  899. switch (blendMode)
  900. {
  901. case RTGUI_BLENDMODE_BLEND:
  902. HLINE(rt_uint16_t, DRAW_SETPIXEL_BLEND_BGR565, draw_end);
  903. break;
  904. case RTGUI_BLENDMODE_ADD:
  905. HLINE(rt_uint16_t, DRAW_SETPIXEL_ADD_BGR565, draw_end);
  906. break;
  907. case RTGUI_BLENDMODE_MOD:
  908. HLINE(rt_uint16_t, DRAW_SETPIXEL_MOD_BGR565, draw_end);
  909. break;
  910. default:
  911. HLINE(rt_uint16_t, DRAW_SETPIXEL_BGR565, draw_end);
  912. break;
  913. }
  914. }
  915. else if (x1 == x2)
  916. {
  917. switch (blendMode)
  918. {
  919. case RTGUI_BLENDMODE_BLEND:
  920. VLINE(rt_uint16_t, DRAW_SETPIXEL_BLEND_BGR565, draw_end);
  921. break;
  922. case RTGUI_BLENDMODE_ADD:
  923. VLINE(rt_uint16_t, DRAW_SETPIXEL_ADD_BGR565, draw_end);
  924. break;
  925. case RTGUI_BLENDMODE_MOD:
  926. VLINE(rt_uint16_t, DRAW_SETPIXEL_MOD_BGR565, draw_end);
  927. break;
  928. default:
  929. VLINE(rt_uint16_t, DRAW_SETPIXEL_BGR565, draw_end);
  930. break;
  931. }
  932. }
  933. else if (ABS(x1 - x2) == ABS(y1 - y2))
  934. {
  935. switch (blendMode)
  936. {
  937. case RTGUI_BLENDMODE_BLEND:
  938. DLINE(rt_uint16_t, DRAW_SETPIXEL_BLEND_BGR565, draw_end);
  939. break;
  940. case RTGUI_BLENDMODE_ADD:
  941. DLINE(rt_uint16_t, DRAW_SETPIXEL_ADD_BGR565, draw_end);
  942. break;
  943. case RTGUI_BLENDMODE_MOD:
  944. DLINE(rt_uint16_t, DRAW_SETPIXEL_MOD_BGR565, draw_end);
  945. break;
  946. default:
  947. DLINE(rt_uint16_t, DRAW_SETPIXEL_BGR565, draw_end);
  948. break;
  949. }
  950. }
  951. else
  952. {
  953. switch (blendMode)
  954. {
  955. case RTGUI_BLENDMODE_BLEND:
  956. AALINE(x1, y1, x2, y2,
  957. DRAW_SETPIXELXY_BLEND_BGR565, DRAW_SETPIXELXY_BLEND_BGR565,
  958. draw_end);
  959. break;
  960. case RTGUI_BLENDMODE_ADD:
  961. AALINE(x1, y1, x2, y2,
  962. DRAW_SETPIXELXY_ADD_BGR565, DRAW_SETPIXELXY_ADD_BGR565,
  963. draw_end);
  964. break;
  965. case RTGUI_BLENDMODE_MOD:
  966. AALINE(x1, y1, x2, y2,
  967. DRAW_SETPIXELXY_MOD_BGR565, DRAW_SETPIXELXY_MOD_BGR565,
  968. draw_end);
  969. break;
  970. default:
  971. AALINE(x1, y1, x2, y2,
  972. DRAW_SETPIXELXY_BGR565, DRAW_SETPIXELXY_BLEND_BGR565,
  973. draw_end);
  974. break;
  975. }
  976. }
  977. }
  978. static void
  979. _dc_blend_line_rgb888(struct rtgui_dc * dst, int x1, int y1, int x2, int y2,
  980. enum RTGUI_BLENDMODE blendMode, rt_uint8_t _r, rt_uint8_t _g, rt_uint8_t _b, rt_uint8_t _a,
  981. rt_bool_t draw_end)
  982. {
  983. unsigned r, g, b, a, inva;
  984. if (blendMode == RTGUI_BLENDMODE_BLEND || blendMode == RTGUI_BLENDMODE_ADD)
  985. {
  986. r = DRAW_MUL(_r, _a);
  987. g = DRAW_MUL(_g, _a);
  988. b = DRAW_MUL(_b, _a);
  989. a = _a;
  990. }
  991. else
  992. {
  993. r = _r;
  994. g = _g;
  995. b = _b;
  996. a = _a;
  997. }
  998. inva = (a ^ 0xff);
  999. if (y1 == y2)
  1000. {
  1001. switch (blendMode)
  1002. {
  1003. case RTGUI_BLENDMODE_BLEND:
  1004. HLINE(rt_uint32_t, DRAW_SETPIXEL_BLEND_RGB888, draw_end);
  1005. break;
  1006. case RTGUI_BLENDMODE_ADD:
  1007. HLINE(rt_uint32_t, DRAW_SETPIXEL_ADD_RGB888, draw_end);
  1008. break;
  1009. case RTGUI_BLENDMODE_MOD:
  1010. HLINE(rt_uint32_t, DRAW_SETPIXEL_MOD_RGB888, draw_end);
  1011. break;
  1012. default:
  1013. HLINE(rt_uint32_t, DRAW_SETPIXEL_RGB888, draw_end);
  1014. break;
  1015. }
  1016. }
  1017. else if (x1 == x2)
  1018. {
  1019. switch (blendMode)
  1020. {
  1021. case RTGUI_BLENDMODE_BLEND:
  1022. VLINE(rt_uint32_t, DRAW_SETPIXEL_BLEND_RGB888, draw_end);
  1023. break;
  1024. case RTGUI_BLENDMODE_ADD:
  1025. VLINE(rt_uint32_t, DRAW_SETPIXEL_ADD_RGB888, draw_end);
  1026. break;
  1027. case RTGUI_BLENDMODE_MOD:
  1028. VLINE(rt_uint32_t, DRAW_SETPIXEL_MOD_RGB888, draw_end);
  1029. break;
  1030. default:
  1031. VLINE(rt_uint32_t, DRAW_SETPIXEL_RGB888, draw_end);
  1032. break;
  1033. }
  1034. }
  1035. else if (ABS(x1 - x2) == ABS(y1 - y2))
  1036. {
  1037. switch (blendMode)
  1038. {
  1039. case RTGUI_BLENDMODE_BLEND:
  1040. DLINE(rt_uint32_t, DRAW_SETPIXEL_BLEND_RGB888, draw_end);
  1041. break;
  1042. case RTGUI_BLENDMODE_ADD:
  1043. DLINE(rt_uint32_t, DRAW_SETPIXEL_ADD_RGB888, draw_end);
  1044. break;
  1045. case RTGUI_BLENDMODE_MOD:
  1046. DLINE(rt_uint32_t, DRAW_SETPIXEL_MOD_RGB888, draw_end);
  1047. break;
  1048. default:
  1049. DLINE(rt_uint32_t, DRAW_SETPIXEL_RGB888, draw_end);
  1050. break;
  1051. }
  1052. }
  1053. else
  1054. {
  1055. switch (blendMode)
  1056. {
  1057. case RTGUI_BLENDMODE_BLEND:
  1058. AALINE(x1, y1, x2, y2,
  1059. DRAW_SETPIXELXY_BLEND_RGB888, DRAW_SETPIXELXY_BLEND_RGB888,
  1060. draw_end);
  1061. break;
  1062. case RTGUI_BLENDMODE_ADD:
  1063. AALINE(x1, y1, x2, y2,
  1064. DRAW_SETPIXELXY_ADD_RGB888, DRAW_SETPIXELXY_ADD_RGB888,
  1065. draw_end);
  1066. break;
  1067. case RTGUI_BLENDMODE_MOD:
  1068. AALINE(x1, y1, x2, y2,
  1069. DRAW_SETPIXELXY_MOD_RGB888, DRAW_SETPIXELXY_MOD_RGB888,
  1070. draw_end);
  1071. break;
  1072. default:
  1073. AALINE(x1, y1, x2, y2,
  1074. DRAW_SETPIXELXY_RGB888, DRAW_SETPIXELXY_BLEND_RGB888,
  1075. draw_end);
  1076. break;
  1077. }
  1078. }
  1079. }
  1080. static void
  1081. _dc_blend_line_argb8888(struct rtgui_dc * dst, int x1, int y1, int x2, int y2,
  1082. enum RTGUI_BLENDMODE blendMode, rt_uint8_t _r, rt_uint8_t _g, rt_uint8_t _b, rt_uint8_t _a,
  1083. rt_bool_t draw_end)
  1084. {
  1085. unsigned r, g, b, a, inva;
  1086. if (blendMode == RTGUI_BLENDMODE_BLEND || blendMode == RTGUI_BLENDMODE_ADD)
  1087. {
  1088. r = DRAW_MUL(_r, _a);
  1089. g = DRAW_MUL(_g, _a);
  1090. b = DRAW_MUL(_b, _a);
  1091. a = _a;
  1092. }
  1093. else
  1094. {
  1095. r = _r;
  1096. g = _g;
  1097. b = _b;
  1098. a = _a;
  1099. }
  1100. inva = (a ^ 0xff);
  1101. if (y1 == y2)
  1102. {
  1103. switch (blendMode)
  1104. {
  1105. case RTGUI_BLENDMODE_BLEND:
  1106. HLINE(rt_uint32_t, DRAW_SETPIXEL_BLEND_ARGB8888, draw_end);
  1107. break;
  1108. case RTGUI_BLENDMODE_ADD:
  1109. HLINE(rt_uint32_t, DRAW_SETPIXEL_ADD_ARGB8888, draw_end);
  1110. break;
  1111. case RTGUI_BLENDMODE_MOD:
  1112. HLINE(rt_uint32_t, DRAW_SETPIXEL_MOD_ARGB8888, draw_end);
  1113. break;
  1114. default:
  1115. HLINE(rt_uint32_t, DRAW_SETPIXEL_ARGB8888, draw_end);
  1116. break;
  1117. }
  1118. }
  1119. else if (x1 == x2)
  1120. {
  1121. switch (blendMode)
  1122. {
  1123. case RTGUI_BLENDMODE_BLEND:
  1124. VLINE(rt_uint32_t, DRAW_SETPIXEL_BLEND_ARGB8888, draw_end);
  1125. break;
  1126. case RTGUI_BLENDMODE_ADD:
  1127. VLINE(rt_uint32_t, DRAW_SETPIXEL_ADD_ARGB8888, draw_end);
  1128. break;
  1129. case RTGUI_BLENDMODE_MOD:
  1130. VLINE(rt_uint32_t, DRAW_SETPIXEL_MOD_ARGB8888, draw_end);
  1131. break;
  1132. default:
  1133. VLINE(rt_uint32_t, DRAW_SETPIXEL_ARGB8888, draw_end);
  1134. break;
  1135. }
  1136. }
  1137. else if (ABS(x1 - x2) == ABS(y1 - y2))
  1138. {
  1139. switch (blendMode)
  1140. {
  1141. case RTGUI_BLENDMODE_BLEND:
  1142. DLINE(rt_uint32_t, DRAW_SETPIXEL_BLEND_ARGB8888, draw_end);
  1143. break;
  1144. case RTGUI_BLENDMODE_ADD:
  1145. DLINE(rt_uint32_t, DRAW_SETPIXEL_ADD_ARGB8888, draw_end);
  1146. break;
  1147. case RTGUI_BLENDMODE_MOD:
  1148. DLINE(rt_uint32_t, DRAW_SETPIXEL_MOD_ARGB8888, draw_end);
  1149. break;
  1150. default:
  1151. DLINE(rt_uint32_t, DRAW_SETPIXEL_ARGB8888, draw_end);
  1152. break;
  1153. }
  1154. }
  1155. else
  1156. {
  1157. switch (blendMode)
  1158. {
  1159. case RTGUI_BLENDMODE_BLEND:
  1160. AALINE(x1, y1, x2, y2,
  1161. DRAW_SETPIXELXY_BLEND_ARGB8888, DRAW_SETPIXELXY_BLEND_ARGB8888,
  1162. draw_end);
  1163. break;
  1164. case RTGUI_BLENDMODE_ADD:
  1165. AALINE(x1, y1, x2, y2,
  1166. DRAW_SETPIXELXY_ADD_ARGB8888, DRAW_SETPIXELXY_ADD_ARGB8888,
  1167. draw_end);
  1168. break;
  1169. case RTGUI_BLENDMODE_MOD:
  1170. AALINE(x1, y1, x2, y2,
  1171. DRAW_SETPIXELXY_MOD_ARGB8888, DRAW_SETPIXELXY_MOD_ARGB8888,
  1172. draw_end);
  1173. break;
  1174. default:
  1175. AALINE(x1, y1, x2, y2,
  1176. DRAW_SETPIXELXY_ARGB8888, DRAW_SETPIXELXY_BLEND_ARGB8888,
  1177. draw_end);
  1178. break;
  1179. }
  1180. }
  1181. }
  1182. typedef void (*BlendLineFunc) (struct rtgui_dc * dst,
  1183. int x1, int y1, int x2, int y2,
  1184. enum RTGUI_BLENDMODE blendMode,
  1185. rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a,
  1186. rt_bool_t draw_end);
  1187. static BlendLineFunc
  1188. _dc_calc_blend_line_func(rt_uint8_t pixel_format)
  1189. {
  1190. switch (pixel_format)
  1191. {
  1192. case RTGRAPHIC_PIXEL_FORMAT_RGB565:
  1193. return _dc_blend_line_rgb565;
  1194. case RTGRAPHIC_PIXEL_FORMAT_BGR565:
  1195. return _dc_blend_line_bgr565;
  1196. case RTGRAPHIC_PIXEL_FORMAT_RGB888:
  1197. return _dc_blend_line_rgb888;
  1198. case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
  1199. return _dc_blend_line_argb8888;
  1200. }
  1201. return NULL;
  1202. }
  1203. static void _do_blend_line(struct rtgui_dc * dst,
  1204. rtgui_color_t color,
  1205. int x1, int y1,
  1206. int x2, int y2,
  1207. enum RTGUI_BLENDMODE blendMode,
  1208. rt_bool_t draw_end)
  1209. {
  1210. BlendLineFunc func;
  1211. rt_uint8_t pixel_format;
  1212. rt_uint8_t r, g, b, a;
  1213. rtgui_widget_t *owner;
  1214. pixel_format = rtgui_dc_get_pixel_format(dst);
  1215. func = _dc_calc_blend_line_func(pixel_format);
  1216. if (!func)
  1217. {
  1218. rt_kprintf("dc_blend_line(): Unsupported pixel format\n");
  1219. return;
  1220. }
  1221. r = RTGUI_RGB_R(color);
  1222. g = RTGUI_RGB_G(color);
  1223. b = RTGUI_RGB_B(color);
  1224. a = RTGUI_RGB_A(color);
  1225. /* perform clip */
  1226. if (dst->type == RTGUI_DC_CLIENT)
  1227. {
  1228. /* get owner */
  1229. owner = RTGUI_CONTAINER_OF(dst, struct rtgui_widget, dc_type);
  1230. x1 = x1 + owner->extent.x1;
  1231. x2 = x2 + owner->extent.x1;
  1232. y1 = y1 + owner->extent.y1;
  1233. y2 = y2 + owner->extent.y1;
  1234. if (owner->clip.data == RT_NULL)
  1235. {
  1236. rtgui_rect_t *prect;
  1237. /* no clip */
  1238. prect = &(owner->clip.extents);
  1239. /* calculate line intersect */
  1240. if (_intersect_rect_line(prect, &x1, &y1, &x2, &y2) == RT_FALSE)
  1241. return;
  1242. /* draw line */
  1243. func(dst, x1, y1, x2, y2, blendMode, r, g, b, a, RT_TRUE);
  1244. }
  1245. else
  1246. {
  1247. register rt_base_t index;
  1248. for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++)
  1249. {
  1250. rtgui_rect_t *prect;
  1251. int draw_x1, draw_x2;
  1252. int draw_y1, draw_y2;
  1253. prect = ((rtgui_rect_t *)(owner->clip.data + index + 1));
  1254. draw_x1 = x1;
  1255. draw_x2 = x2;
  1256. draw_y1 = y1;
  1257. draw_y2 = y2;
  1258. /* calculate line intersect */
  1259. if (_intersect_rect_line(prect, &draw_x1, &draw_y1, &draw_x2, &draw_y2) == RT_FALSE)
  1260. continue;
  1261. /* draw line */
  1262. func(dst, draw_x1, draw_y1, draw_x2, draw_y2, blendMode, r, g, b, a, RT_TRUE);
  1263. }
  1264. }
  1265. }
  1266. else
  1267. {
  1268. if (dst->type == RTGUI_DC_HW)
  1269. {
  1270. rtgui_rect_t *prect;
  1271. struct rtgui_dc_hw *dc_hw = (struct rtgui_dc_hw*)dst;
  1272. owner = dc_hw->owner;
  1273. x1 = x1 + owner->extent.x1;
  1274. x2 = x2 + owner->extent.x1;
  1275. y1 = y1 + owner->extent.y1;
  1276. y2 = y2 + owner->extent.y1;
  1277. prect = &(owner->clip.extents);
  1278. if (_intersect_rect_line(prect, &x1, &y1, &x2, &y2) == RT_FALSE)
  1279. return;
  1280. }
  1281. func(dst, x1, y1, x2, y2, blendMode, r, g, b, a, RT_TRUE);
  1282. }
  1283. }
  1284. void
  1285. rtgui_dc_blend_line(struct rtgui_dc * dst, int x1, int y1, int x2, int y2,
  1286. enum RTGUI_BLENDMODE blendMode, rtgui_color_t color)
  1287. {
  1288. RT_ASSERT(dst != RT_NULL);
  1289. if (!rtgui_dc_get_visible(dst))
  1290. return;
  1291. /* we do not support pixel DC */
  1292. if (_dc_get_pixel(dst, 0, 0) == RT_NULL)
  1293. return;
  1294. _do_blend_line(dst, color, x1, y1, x2, y2, blendMode, RT_FALSE);
  1295. }
  1296. RTM_EXPORT(rtgui_dc_blend_line);
  1297. void
  1298. rtgui_dc_blend_lines(struct rtgui_dc * dst, const rtgui_point_t * points, int count,
  1299. enum RTGUI_BLENDMODE blendMode, rtgui_color_t color)
  1300. {
  1301. int i;
  1302. RT_ASSERT(dst != RT_NULL);
  1303. if (!rtgui_dc_get_visible(dst))
  1304. return;
  1305. /* we do not support pixel DC */
  1306. if (_dc_get_pixel(dst, 0, 0) == RT_NULL)
  1307. return;
  1308. for (i = 1; i < count; ++i)
  1309. {
  1310. rt_bool_t draw_end;
  1311. int x1, y1, x2, y2;
  1312. x1 = points[i-1].x;
  1313. y1 = points[i-1].y;
  1314. x2 = points[i].x;
  1315. y2 = points[i].y;
  1316. /* Draw the end if it was clipped */
  1317. draw_end = (x2 != points[i].x || y2 != points[i].y);
  1318. _do_blend_line(dst, color, x1, y1, x2, y2, blendMode, draw_end);
  1319. }
  1320. if (points[0].x != points[count-1].x || points[0].y != points[count-1].y)
  1321. {
  1322. rt_uint8_t r, g, b, a;
  1323. r = RTGUI_RGB_R(color);
  1324. g = RTGUI_RGB_G(color);
  1325. b = RTGUI_RGB_B(color);
  1326. a = RTGUI_RGB_A(color);
  1327. rtgui_dc_blend_point(dst, points[count-1].x, points[count-1].y,
  1328. blendMode, r, g, b, a);
  1329. }
  1330. }
  1331. RTM_EXPORT(rtgui_dc_blend_lines);
  1332. static void
  1333. _dc_blend_fill_rect_rgb565(struct rtgui_dc * dst, const rtgui_rect_t * rect,
  1334. enum RTGUI_BLENDMODE blendMode, rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
  1335. {
  1336. unsigned inva = 0xff - a;
  1337. switch (blendMode)
  1338. {
  1339. case RTGUI_BLENDMODE_BLEND:
  1340. FILLRECT(rt_uint16_t, DRAW_SETPIXEL_BLEND_RGB565);
  1341. break;
  1342. case RTGUI_BLENDMODE_ADD:
  1343. FILLRECT(rt_uint16_t, DRAW_SETPIXEL_ADD_RGB565);
  1344. break;
  1345. case RTGUI_BLENDMODE_MOD:
  1346. FILLRECT(rt_uint16_t, DRAW_SETPIXEL_MOD_RGB565);
  1347. break;
  1348. default:
  1349. FILLRECT(rt_uint16_t, DRAW_SETPIXEL_RGB565);
  1350. break;
  1351. }
  1352. }
  1353. static void
  1354. _dc_blend_fill_rect_bgr565(struct rtgui_dc * dst, const rtgui_rect_t * rect,
  1355. enum RTGUI_BLENDMODE blendMode, rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
  1356. {
  1357. unsigned inva = 0xff - a;
  1358. switch (blendMode)
  1359. {
  1360. case RTGUI_BLENDMODE_BLEND:
  1361. FILLRECT(rt_uint16_t, DRAW_SETPIXEL_BLEND_RGB565);
  1362. break;
  1363. case RTGUI_BLENDMODE_ADD:
  1364. FILLRECT(rt_uint16_t, DRAW_SETPIXEL_ADD_RGB565);
  1365. break;
  1366. case RTGUI_BLENDMODE_MOD:
  1367. FILLRECT(rt_uint16_t, DRAW_SETPIXEL_MOD_RGB565);
  1368. break;
  1369. default:
  1370. FILLRECT(rt_uint16_t, DRAW_SETPIXEL_RGB565);
  1371. break;
  1372. }
  1373. }
  1374. static void
  1375. _dc_blend_fill_rect_rgb888(struct rtgui_dc * dst, const rtgui_rect_t * rect,
  1376. enum RTGUI_BLENDMODE blendMode, rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
  1377. {
  1378. unsigned inva = 0xff - a;
  1379. switch (blendMode)
  1380. {
  1381. case RTGUI_BLENDMODE_BLEND:
  1382. FILLRECT(rt_uint32_t, DRAW_SETPIXEL_BLEND_RGB888);
  1383. break;
  1384. case RTGUI_BLENDMODE_ADD:
  1385. FILLRECT(rt_uint32_t, DRAW_SETPIXEL_ADD_RGB888);
  1386. break;
  1387. case RTGUI_BLENDMODE_MOD:
  1388. FILLRECT(rt_uint32_t, DRAW_SETPIXEL_MOD_RGB888);
  1389. break;
  1390. default:
  1391. FILLRECT(rt_uint32_t, DRAW_SETPIXEL_RGB888);
  1392. break;
  1393. }
  1394. }
  1395. static void
  1396. _dc_blend_fill_rect_argb8888(struct rtgui_dc * dst, const rtgui_rect_t * rect,
  1397. enum RTGUI_BLENDMODE blendMode, rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
  1398. {
  1399. unsigned inva = 0xff - a;
  1400. switch (blendMode)
  1401. {
  1402. case RTGUI_BLENDMODE_BLEND:
  1403. FILLRECT(rt_uint32_t, DRAW_SETPIXEL_BLEND_ARGB8888);
  1404. break;
  1405. case RTGUI_BLENDMODE_ADD:
  1406. FILLRECT(rt_uint32_t, DRAW_SETPIXEL_ADD_ARGB8888);
  1407. break;
  1408. case RTGUI_BLENDMODE_MOD:
  1409. FILLRECT(rt_uint32_t, DRAW_SETPIXEL_MOD_ARGB8888);
  1410. break;
  1411. default:
  1412. FILLRECT(rt_uint32_t, DRAW_SETPIXEL_ARGB8888);
  1413. break;
  1414. }
  1415. }
  1416. typedef void (*BlendFillFunc)(struct rtgui_dc * dst, const rtgui_rect_t * rect,
  1417. enum RTGUI_BLENDMODE blendMode, rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a);
  1418. void
  1419. rtgui_dc_blend_fill_rect(struct rtgui_dc* dst, const rtgui_rect_t *rect,
  1420. enum RTGUI_BLENDMODE blendMode, rtgui_color_t color)
  1421. {
  1422. unsigned r, g, b, a;
  1423. BlendFillFunc func = RT_NULL;
  1424. RT_ASSERT(dst != RT_NULL);
  1425. if (!rtgui_dc_get_visible(dst)) return;
  1426. /* This function doesn't work on surfaces < 8 bpp */
  1427. if (_dc_get_bits_per_pixel(dst) < 8)
  1428. {
  1429. rt_kprintf("dc_blend_fill_rect(): Unsupported pixel format\n");
  1430. return ;
  1431. }
  1432. r = RTGUI_RGB_R(color);
  1433. g = RTGUI_RGB_G(color);
  1434. b = RTGUI_RGB_B(color);
  1435. a = RTGUI_RGB_A(color);
  1436. if (blendMode == RTGUI_BLENDMODE_BLEND || blendMode == RTGUI_BLENDMODE_ADD)
  1437. {
  1438. r = DRAW_MUL(r, a);
  1439. g = DRAW_MUL(g, a);
  1440. b = DRAW_MUL(b, a);
  1441. }
  1442. switch (rtgui_dc_get_pixel_format(dst))
  1443. {
  1444. case RTGRAPHIC_PIXEL_FORMAT_RGB565:
  1445. func = _dc_blend_fill_rect_rgb565;
  1446. break;
  1447. case RTGRAPHIC_PIXEL_FORMAT_BGR565:
  1448. func = _dc_blend_fill_rect_bgr565;
  1449. break;
  1450. case RTGRAPHIC_PIXEL_FORMAT_RGB888:
  1451. func = _dc_blend_fill_rect_rgb888;
  1452. break;
  1453. case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
  1454. func = _dc_blend_fill_rect_argb8888;
  1455. break;
  1456. default:
  1457. break;
  1458. }
  1459. if (func == RT_NULL)
  1460. {
  1461. rt_kprintf("dc_blend_fill_rect(): Unsupported pixel format\n");
  1462. return ;
  1463. }
  1464. if (dst->type == RTGUI_DC_CLIENT)
  1465. {
  1466. register rt_base_t index;
  1467. rtgui_widget_t *owner;
  1468. rtgui_rect_t draw_rect;
  1469. /* get owner */
  1470. owner = RTGUI_CONTAINER_OF(dst, struct rtgui_widget, dc_type);
  1471. if (owner->clip.data == RT_NULL)
  1472. {
  1473. rtgui_rect_t *prect;
  1474. prect = &(owner->clip.extents);
  1475. /* convert logic to device */
  1476. draw_rect = *rect;
  1477. rtgui_rect_move(&draw_rect,owner->extent.x1, owner->extent.y1);
  1478. /* calculate rect intersect */
  1479. if (prect->y1 > draw_rect.y2 || prect->y2 <= draw_rect.y1) return ;
  1480. if (prect->x2 <= draw_rect.x1 || prect->x1 > draw_rect.x2 ) return ;
  1481. rtgui_rect_intersect(prect, &draw_rect);
  1482. func(dst, &draw_rect, blendMode, r, g, b, a);
  1483. }
  1484. else
  1485. {
  1486. for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++)
  1487. {
  1488. rtgui_rect_t *prect;
  1489. prect = ((rtgui_rect_t *)(owner->clip.data + index + 1));
  1490. draw_rect = *rect;
  1491. rtgui_rect_move(&draw_rect,owner->extent.x1, owner->extent.y1);
  1492. /* calculate rect intersect */
  1493. if (prect->y1 > draw_rect.y2 || prect->y2 <= draw_rect.y1) continue;
  1494. if (prect->x2 <= draw_rect.x1 || prect->x1 > draw_rect.x2 ) continue;
  1495. rtgui_rect_intersect(prect, &draw_rect);
  1496. func(dst, &draw_rect, blendMode, r, g, b, a);
  1497. }
  1498. }
  1499. }
  1500. else if (dst->type == RTGUI_DC_HW)
  1501. {
  1502. rtgui_rect_t draw_rect = *rect;
  1503. struct rtgui_dc_hw *dc = (struct rtgui_dc_hw *) dst;
  1504. draw_rect.x2 = dc->owner->extent.x1 + draw_rect.x2 - draw_rect.x1;
  1505. draw_rect.y2 = dc->owner->extent.y1 + draw_rect.y2 - draw_rect.y1;
  1506. draw_rect.x1 = dc->owner->extent.x1 > 0 ? dc->owner->extent.x1 : 0;
  1507. draw_rect.y1 = dc->owner->extent.y1 > 0 ? dc->owner->extent.y1 : 0;
  1508. draw_rect.x2 = draw_rect.x2 > hw_driver->width ? hw_driver->width : draw_rect.x2;
  1509. draw_rect.y2 = draw_rect.y2 > hw_driver->height ? hw_driver->height : draw_rect.y2;
  1510. func(dst, &draw_rect, blendMode, r, g, b, a);
  1511. }
  1512. else
  1513. {
  1514. func(dst, rect, blendMode, r, g, b, a);
  1515. }
  1516. }
  1517. RTM_EXPORT(rtgui_dc_blend_fill_rect);
  1518. void
  1519. rtgui_dc_blend_fill_rects(struct rtgui_dc * dst, const rtgui_rect_t *rects, int count,
  1520. enum RTGUI_BLENDMODE blendMode, rtgui_color_t color)
  1521. {
  1522. int i;
  1523. rtgui_rect_t rect;
  1524. BlendFillFunc func = RT_NULL;
  1525. rt_uint8_t r, g, b, a;
  1526. rtgui_widget_t *owner = RT_NULL;
  1527. RT_ASSERT(dst != RT_NULL);
  1528. if (!rtgui_dc_get_visible(dst)) return;
  1529. /* This function doesn't work on surfaces < 8 bpp */
  1530. if (_dc_get_bits_per_pixel(dst)< 8)
  1531. {
  1532. rt_kprintf("dc_blend_fill_rects(): Unsupported pixel format\n");
  1533. return;
  1534. }
  1535. r = RTGUI_RGB_R(color);
  1536. g = RTGUI_RGB_G(color);
  1537. b = RTGUI_RGB_B(color);
  1538. a = RTGUI_RGB_A(color);
  1539. if (blendMode == RTGUI_BLENDMODE_BLEND || blendMode == RTGUI_BLENDMODE_ADD)
  1540. {
  1541. r = DRAW_MUL(r, a);
  1542. g = DRAW_MUL(g, a);
  1543. b = DRAW_MUL(b, a);
  1544. }
  1545. switch (rtgui_dc_get_pixel_format(dst))
  1546. {
  1547. case RTGRAPHIC_PIXEL_FORMAT_RGB565:
  1548. func = _dc_blend_fill_rect_rgb565;
  1549. break;
  1550. case RTGRAPHIC_PIXEL_FORMAT_BGR565:
  1551. func = _dc_blend_fill_rect_bgr565;
  1552. break;
  1553. case RTGRAPHIC_PIXEL_FORMAT_RGB888:
  1554. func = _dc_blend_fill_rect_rgb888;
  1555. break;
  1556. case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
  1557. func = _dc_blend_fill_rect_argb8888;
  1558. break;
  1559. default:
  1560. break;
  1561. }
  1562. if (func == RT_NULL)
  1563. {
  1564. rt_kprintf("dc_blend_fill_rects(): Unsupported pixel format\n");
  1565. return;
  1566. }
  1567. if (dst->type == RTGUI_DC_CLIENT)
  1568. {
  1569. /* get owner */
  1570. owner = RTGUI_CONTAINER_OF(dst, struct rtgui_widget, dc_type);
  1571. }
  1572. for (i = 0; i < count; ++i)
  1573. {
  1574. rect = rects[i];
  1575. if (dst->type == RTGUI_DC_CLIENT)
  1576. {
  1577. register rt_base_t index;
  1578. rtgui_rect_t draw_rect;
  1579. if (owner->clip.data == RT_NULL)
  1580. {
  1581. rtgui_rect_t *prect;
  1582. prect = &(owner->clip.extents);
  1583. /* convert logic to device */
  1584. draw_rect = rect;
  1585. rtgui_rect_move(&draw_rect,owner->extent.x1, owner->extent.y1);
  1586. /* calculate rect intersect */
  1587. if (prect->y1 > draw_rect.y2 || prect->y2 <= draw_rect.y1) return ;
  1588. if (prect->x2 <= draw_rect.x1 || prect->x1 > draw_rect.x2 ) return ;
  1589. rtgui_rect_intersect(prect, &draw_rect);
  1590. func(dst, &draw_rect, blendMode, r, g, b, a);
  1591. }
  1592. else
  1593. {
  1594. for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++)
  1595. {
  1596. rtgui_rect_t *prect;
  1597. prect = ((rtgui_rect_t *)(owner->clip.data + index + 1));
  1598. draw_rect = rect;
  1599. rtgui_rect_move(&draw_rect,owner->extent.x1, owner->extent.y1);
  1600. /* calculate rect intersect */
  1601. if (prect->y1 > draw_rect.y2 || prect->y2 <= draw_rect.y1) continue;
  1602. if (prect->x2 <= draw_rect.x1 || prect->x1 > draw_rect.x2 ) continue;
  1603. rtgui_rect_intersect(prect, &draw_rect);
  1604. func(dst, &draw_rect, blendMode, r, g, b, a);
  1605. }
  1606. }
  1607. }
  1608. else
  1609. {
  1610. func(dst, &rect, blendMode, r, g, b, a);
  1611. }
  1612. }
  1613. }
  1614. RTM_EXPORT(rtgui_dc_blend_fill_rects);
  1615. /* Windows targets do not have lrint, so provide a local inline version */
  1616. #if defined(_MSC_VER)
  1617. /* Detect 64bit and use intrinsic version */
  1618. #ifdef _M_X64
  1619. #include <emmintrin.h>
  1620. static __inline long
  1621. lrint(float f)
  1622. {
  1623. return _mm_cvtss_si32(_mm_load_ss(&f));
  1624. }
  1625. #elif defined(_M_IX86)
  1626. __inline long int
  1627. lrint (double flt)
  1628. {
  1629. int intgr;
  1630. _asm
  1631. {
  1632. fld flt
  1633. fistp intgr
  1634. };
  1635. return intgr;
  1636. }
  1637. #elif defined(_M_ARM)
  1638. #include <armintr.h>
  1639. #pragma warning(push)
  1640. #pragma warning(disable: 4716)
  1641. __declspec(naked) long int
  1642. lrint (double flt)
  1643. {
  1644. __emit(0xEC410B10); // fmdrr d0, r0, r1
  1645. __emit(0xEEBD0B40); // ftosid s0, d0
  1646. __emit(0xEE100A10); // fmrs r0, s0
  1647. __emit(0xE12FFF1E); // bx lr
  1648. }
  1649. #pragma warning(pop)
  1650. #else
  1651. #error lrint needed for MSVC on non X86/AMD64/ARM targets.
  1652. #endif
  1653. #endif
  1654. rt_inline void _draw_pixel_weight(struct rtgui_dc * dc, rt_int16_t x, rt_int16_t y,
  1655. rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a, rt_uint32_t weight)
  1656. {
  1657. /*
  1658. * Modify Alpha by weight
  1659. */
  1660. rt_uint32_t ax = a;
  1661. ax = ((ax * weight) >> 8);
  1662. if (ax > 255)
  1663. {
  1664. a = 255;
  1665. }
  1666. else
  1667. {
  1668. a = (rt_uint8_t)(ax & 0x000000ff);
  1669. }
  1670. rtgui_dc_blend_point(dc, x, y, RTGUI_BLENDMODE_BLEND, r, g, b, a);
  1671. }
  1672. void rtgui_dc_draw_aa_ellipse(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry)
  1673. {
  1674. int i;
  1675. int a2, b2, ds, dt, dxt, t, s, d;
  1676. rt_int16_t xp, yp, xs, ys, od, dyt, xx, yy, xc2, yc2;
  1677. int cp;
  1678. double sab;
  1679. rt_uint8_t weight, iweight;
  1680. rt_uint8_t r, g, b, a;
  1681. /* Sanity check radii */
  1682. if ((rx < 0) || (ry < 0)) return ;
  1683. /*
  1684. * Special case for rx=0 - draw a vline
  1685. */
  1686. if (rx == 0)
  1687. {
  1688. rtgui_dc_draw_vline(dc, x, y - ry, y + ry);
  1689. return;
  1690. }
  1691. /*
  1692. * Special case for ry=0 - draw an hline
  1693. */
  1694. if (ry == 0)
  1695. {
  1696. rtgui_dc_draw_hline(dc, x - rx, x + rx, y);
  1697. return;
  1698. }
  1699. /* Variable setup */
  1700. r = RTGUI_RGB_R(RTGUI_DC_FC(dc));
  1701. g = RTGUI_RGB_G(RTGUI_DC_FC(dc));
  1702. b = RTGUI_RGB_B(RTGUI_DC_FC(dc));
  1703. a = RTGUI_RGB_A(RTGUI_DC_FC(dc));
  1704. a2 = rx * rx;
  1705. b2 = ry * ry;
  1706. ds = 2 * a2;
  1707. dt = 2 * b2;
  1708. xc2 = 2 * x;
  1709. yc2 = 2 * y;
  1710. sab = sqrt((double)(a2 + b2));
  1711. od = (rt_int16_t)lrint(sab*0.01) + 1; /* introduce some overdraw */
  1712. dxt = (rt_int16_t)lrint((double)a2 / sab) + od;
  1713. t = 0;
  1714. s = -2 * a2 * ry;
  1715. d = 0;
  1716. xp = x;
  1717. yp = y - ry;
  1718. /* Draw */
  1719. /* "End points" */
  1720. rtgui_dc_blend_point(dc, xp, yp, RTGUI_BLENDMODE_NONE, r, g, b, a);
  1721. rtgui_dc_blend_point(dc, xc2 - xp, yp, RTGUI_BLENDMODE_NONE, r, g, b, a);
  1722. rtgui_dc_blend_point(dc, xp, yc2 - yp, RTGUI_BLENDMODE_NONE, r, g, b, a);
  1723. rtgui_dc_blend_point(dc, xc2 - xp, yc2 - yp, RTGUI_BLENDMODE_NONE, r, g, b, a);
  1724. for (i = 1; i <= dxt; i++)
  1725. {
  1726. xp--;
  1727. d += t - b2;
  1728. if (d >= 0)
  1729. ys = yp - 1;
  1730. else if ((d - s - a2) > 0)
  1731. {
  1732. if ((2 * d - s - a2) >= 0)
  1733. ys = yp + 1;
  1734. else
  1735. {
  1736. ys = yp;
  1737. yp++;
  1738. d -= s + a2;
  1739. s += ds;
  1740. }
  1741. }
  1742. else
  1743. {
  1744. yp++;
  1745. ys = yp + 1;
  1746. d -= s + a2;
  1747. s += ds;
  1748. }
  1749. t -= dt;
  1750. /* Calculate alpha */
  1751. if (s != 0)
  1752. {
  1753. cp = 255 * abs(d) / abs(s);
  1754. if (cp > 255)
  1755. {
  1756. cp = 255;
  1757. }
  1758. }
  1759. else
  1760. {
  1761. cp = 255;
  1762. }
  1763. /* Calculate weights */
  1764. weight = cp;
  1765. iweight = 255 - weight;
  1766. /* Upper half */
  1767. xx = xc2 - xp;
  1768. _draw_pixel_weight(dc, xp, yp, r, g, b, a, iweight);
  1769. _draw_pixel_weight(dc, xx, yp, r, g, b, a, iweight);
  1770. _draw_pixel_weight(dc, xp, ys, r, g, b, a, weight);
  1771. _draw_pixel_weight(dc, xx, ys, r, g, b, a, weight);
  1772. /* Lower half */
  1773. yy = yc2 - yp;
  1774. _draw_pixel_weight(dc, xp, yy, r, g, b, a, iweight);
  1775. _draw_pixel_weight(dc, xx, yy, r, g, b, a, iweight);
  1776. yy = yc2 - ys;
  1777. _draw_pixel_weight(dc, xp, yy, r, g, b, a, weight);
  1778. _draw_pixel_weight(dc, xx, yy, r, g, b, a, weight);
  1779. }
  1780. /* Replaces original approximation code dyt = abs(yp - yc); */
  1781. dyt = (rt_int16_t)lrint((double)b2 / sab ) + od;
  1782. for (i = 1; i <= dyt; i++)
  1783. {
  1784. yp++;
  1785. d -= s + a2;
  1786. if (d <= 0)
  1787. xs = xp + 1;
  1788. else if ((d + t - b2) < 0)
  1789. {
  1790. if ((2 * d + t - b2) <= 0)
  1791. xs = xp - 1;
  1792. else
  1793. {
  1794. xs = xp;
  1795. xp--;
  1796. d += t - b2;
  1797. t -= dt;
  1798. }
  1799. }
  1800. else
  1801. {
  1802. xp--;
  1803. xs = xp - 1;
  1804. d += t - b2;
  1805. t -= dt;
  1806. }
  1807. s += ds;
  1808. /* Calculate alpha */
  1809. if (t != 0)
  1810. {
  1811. cp = 255 * abs(d) / abs(t);
  1812. if (cp > 255)
  1813. {
  1814. cp = 255;
  1815. }
  1816. }
  1817. else
  1818. {
  1819. cp = 255;
  1820. }
  1821. /* Calculate weight */
  1822. weight = cp;
  1823. iweight = 255 - weight;
  1824. /* Left half */
  1825. xx = xc2 - xp;
  1826. yy = yc2 - yp;
  1827. _draw_pixel_weight(dc, xp, yp, r, g, b, a, iweight);
  1828. _draw_pixel_weight(dc, xx, yp, r, g, b, a, iweight);
  1829. _draw_pixel_weight(dc, xp, yy, r, g, b, a, iweight);
  1830. _draw_pixel_weight(dc, xx, yy, r, g, b, a, iweight);
  1831. /* Right half */
  1832. xx = xc2 - xs;
  1833. _draw_pixel_weight(dc, xs, yp, r, g, b, a, weight);
  1834. _draw_pixel_weight(dc, xx, yp, r, g, b, a, weight);
  1835. _draw_pixel_weight(dc, xs, yy, r, g, b, a, weight);
  1836. _draw_pixel_weight(dc, xx, yy, r, g, b, a, weight);
  1837. }
  1838. }
  1839. RTM_EXPORT(rtgui_dc_draw_aa_ellipse);
  1840. void rtgui_dc_draw_aa_circle(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t r)
  1841. {
  1842. rtgui_dc_draw_aa_ellipse(dc, x, y, r, r);
  1843. }
  1844. RTM_EXPORT(rtgui_dc_draw_aa_circle);
  1845. /*!
  1846. \brief The structure passed to the internal Bresenham iterator.
  1847. */
  1848. typedef struct
  1849. {
  1850. rt_int16_t x, y;
  1851. int dx, dy, s1, s2, swapdir, error;
  1852. rt_uint32_t count;
  1853. } _BresenhamIterator;
  1854. /*!
  1855. \brief The structure passed to the internal Murphy iterator.
  1856. */
  1857. typedef struct
  1858. {
  1859. rt_uint32_t color;
  1860. struct rtgui_dc *dst;
  1861. int u, v; /* delta x , delta y */
  1862. int ku, kt, kv, kd; /* loop constants */
  1863. int oct2;
  1864. int quad4;
  1865. rt_int16_t last1x, last1y, last2x, last2y, first1x, first1y, first2x, first2y, tempx, tempy;
  1866. } _MurphyIterator;
  1867. /*!
  1868. \brief Internal function to initialize the Bresenham line iterator.
  1869. Example of use:
  1870. _BresenhamIterator b;
  1871. _bresenhamInitialize (&b, x1, y1, x2, y2);
  1872. do {
  1873. plot(b.x, b.y);
  1874. } while (_bresenhamIterate(&b)==0);
  1875. \param b Pointer to struct for bresenham line drawing state.
  1876. \param x1 X coordinate of the first point of the line.
  1877. \param y1 Y coordinate of the first point of the line.
  1878. \param x2 X coordinate of the second point of the line.
  1879. \param y2 Y coordinate of the second point of the line.
  1880. \returns Returns 0 on success, -1 on failure.
  1881. */
  1882. int _bresenhamInitialize(_BresenhamIterator *b, rt_int16_t x1, rt_int16_t y1, rt_int16_t x2, rt_int16_t y2)
  1883. {
  1884. int temp;
  1885. if (b==NULL)
  1886. {
  1887. return(-1);
  1888. }
  1889. b->x = x1;
  1890. b->y = y1;
  1891. /* dx = abs(x2-x1), s1 = sign(x2-x1) */
  1892. if ((b->dx = x2 - x1) != 0)
  1893. {
  1894. if (b->dx < 0)
  1895. {
  1896. b->dx = -b->dx;
  1897. b->s1 = -1;
  1898. }
  1899. else
  1900. {
  1901. b->s1 = 1;
  1902. }
  1903. }
  1904. else
  1905. {
  1906. b->s1 = 0;
  1907. }
  1908. /* dy = abs(y2-y1), s2 = sign(y2-y1) */
  1909. if ((b->dy = y2 - y1) != 0)
  1910. {
  1911. if (b->dy < 0)
  1912. {
  1913. b->dy = -b->dy;
  1914. b->s2 = -1;
  1915. }
  1916. else
  1917. {
  1918. b->s2 = 1;
  1919. }
  1920. }
  1921. else
  1922. {
  1923. b->s2 = 0;
  1924. }
  1925. if (b->dy > b->dx)
  1926. {
  1927. temp = b->dx;
  1928. b->dx = b->dy;
  1929. b->dy = temp;
  1930. b->swapdir = 1;
  1931. }
  1932. else
  1933. {
  1934. b->swapdir = 0;
  1935. }
  1936. b->count = (b->dx<0) ? 0 : (unsigned int)b->dx;
  1937. b->dy <<= 1;
  1938. b->error = b->dy - b->dx;
  1939. b->dx <<= 1;
  1940. return(0);
  1941. }
  1942. /*!
  1943. \brief Internal function to move Bresenham line iterator to the next position.
  1944. Maybe updates the x and y coordinates of the iterator struct.
  1945. \param b Pointer to struct for bresenham line drawing state.
  1946. \returns Returns 0 on success, 1 if last point was reached, 2 if moving past end-of-line, -1 on failure.
  1947. */
  1948. int _bresenhamIterate(_BresenhamIterator *b)
  1949. {
  1950. if (b==NULL)
  1951. {
  1952. return (-1);
  1953. }
  1954. /* last point check */
  1955. if (b->count==0)
  1956. {
  1957. return (2);
  1958. }
  1959. while (b->error >= 0)
  1960. {
  1961. if (b->swapdir)
  1962. {
  1963. b->x += b->s1;
  1964. }
  1965. else
  1966. {
  1967. b->y += b->s2;
  1968. }
  1969. b->error -= b->dx;
  1970. }
  1971. if (b->swapdir)
  1972. {
  1973. b->y += b->s2;
  1974. }
  1975. else
  1976. {
  1977. b->x += b->s1;
  1978. }
  1979. b->error += b->dy;
  1980. b->count--;
  1981. /* count==0 indicates "end-of-line" */
  1982. return ((b->count) ? 0 : 1);
  1983. }
  1984. /*!
  1985. \brief Internal function to to draw parallel lines with Murphy algorithm.
  1986. \param m Pointer to struct for murphy iterator.
  1987. \param x X coordinate of point.
  1988. \param y Y coordinate of point.
  1989. \param d1 Direction square/diagonal.
  1990. */
  1991. void _murphyParaline(_MurphyIterator *m, rt_int16_t x, rt_int16_t y, int d1)
  1992. {
  1993. int p;
  1994. d1 = -d1;
  1995. for (p = 0; p <= m->u; p++)
  1996. {
  1997. rtgui_dc_draw_point(m->dst, x, y);
  1998. if (d1 <= m->kt)
  1999. {
  2000. if (m->oct2 == 0)
  2001. {
  2002. x++;
  2003. }
  2004. else
  2005. {
  2006. if (m->quad4 == 0)
  2007. {
  2008. y++;
  2009. }
  2010. else
  2011. {
  2012. y--;
  2013. }
  2014. }
  2015. d1 += m->kv;
  2016. }
  2017. else
  2018. {
  2019. x++;
  2020. if (m->quad4 == 0)
  2021. {
  2022. y++;
  2023. }
  2024. else
  2025. {
  2026. y--;
  2027. }
  2028. d1 += m->kd;
  2029. }
  2030. }
  2031. m->tempx = x;
  2032. m->tempy = y;
  2033. }
  2034. /*!
  2035. \brief Internal function to to draw one iteration of the Murphy algorithm.
  2036. \param m Pointer to struct for murphy iterator.
  2037. \param miter Iteration count.
  2038. \param ml1bx X coordinate of a point.
  2039. \param ml1by Y coordinate of a point.
  2040. \param ml2bx X coordinate of a point.
  2041. \param ml2by Y coordinate of a point.
  2042. \param ml1x X coordinate of a point.
  2043. \param ml1y Y coordinate of a point.
  2044. \param ml2x X coordinate of a point.
  2045. \param ml2y Y coordinate of a point.
  2046. */
  2047. void _murphyIteration(_MurphyIterator *m, rt_uint8_t miter,
  2048. rt_uint16_t ml1bx, rt_uint16_t ml1by, rt_uint16_t ml2bx, rt_uint16_t ml2by,
  2049. rt_uint16_t ml1x, rt_uint16_t ml1y, rt_uint16_t ml2x, rt_uint16_t ml2y)
  2050. {
  2051. int atemp1, atemp2;
  2052. int ftmp1, ftmp2;
  2053. rt_uint16_t m1x, m1y, m2x, m2y;
  2054. rt_uint16_t fix, fiy, lax, lay, curx, cury;
  2055. int px[4], py[4];
  2056. _BresenhamIterator b;
  2057. if (miter > 1)
  2058. {
  2059. if (m->first1x != -32768)
  2060. {
  2061. fix = (m->first1x + m->first2x) / 2;
  2062. fiy = (m->first1y + m->first2y) / 2;
  2063. lax = (m->last1x + m->last2x) / 2;
  2064. lay = (m->last1y + m->last2y) / 2;
  2065. curx = (ml1x + ml2x) / 2;
  2066. cury = (ml1y + ml2y) / 2;
  2067. atemp1 = (fix - curx);
  2068. atemp2 = (fiy - cury);
  2069. ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
  2070. atemp1 = (lax - curx);
  2071. atemp2 = (lay - cury);
  2072. ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
  2073. if (ftmp1 <= ftmp2)
  2074. {
  2075. m1x = m->first1x;
  2076. m1y = m->first1y;
  2077. m2x = m->first2x;
  2078. m2y = m->first2y;
  2079. }
  2080. else
  2081. {
  2082. m1x = m->last1x;
  2083. m1y = m->last1y;
  2084. m2x = m->last2x;
  2085. m2y = m->last2y;
  2086. }
  2087. atemp1 = (m2x - ml2x);
  2088. atemp2 = (m2y - ml2y);
  2089. ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
  2090. atemp1 = (m2x - ml2bx);
  2091. atemp2 = (m2y - ml2by);
  2092. ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
  2093. if (ftmp2 >= ftmp1)
  2094. {
  2095. ftmp1 = ml2bx;
  2096. ftmp2 = ml2by;
  2097. ml2bx = ml2x;
  2098. ml2by = ml2y;
  2099. ml2x = ftmp1;
  2100. ml2y = ftmp2;
  2101. ftmp1 = ml1bx;
  2102. ftmp2 = ml1by;
  2103. ml1bx = ml1x;
  2104. ml1by = ml1y;
  2105. ml1x = ftmp1;
  2106. ml1y = ftmp2;
  2107. }
  2108. _bresenhamInitialize(&b, m2x, m2y, m1x, m1y);
  2109. do
  2110. {
  2111. rtgui_dc_draw_color_point(m->dst, b.x, b.y, m->color);
  2112. }
  2113. while (_bresenhamIterate(&b)==0);
  2114. _bresenhamInitialize(&b, m1x, m1y, ml1bx, ml1by);
  2115. do
  2116. {
  2117. rtgui_dc_draw_color_point(m->dst, b.x, b.y, m->color);
  2118. }
  2119. while (_bresenhamIterate(&b)==0);
  2120. _bresenhamInitialize(&b, ml1bx, ml1by, ml2bx, ml2by);
  2121. do
  2122. {
  2123. rtgui_dc_draw_color_point(m->dst, b.x, b.y, m->color);
  2124. }
  2125. while (_bresenhamIterate(&b)==0);
  2126. _bresenhamInitialize(&b, ml2bx, ml2by, m2x, m2y);
  2127. do
  2128. {
  2129. rtgui_dc_draw_color_point(m->dst, b.x, b.y, m->color);
  2130. }
  2131. while (_bresenhamIterate(&b)==0);
  2132. px[0] = m1x;
  2133. px[1] = m2x;
  2134. px[2] = ml1bx;
  2135. px[3] = ml2bx;
  2136. py[0] = m1y;
  2137. py[1] = m2y;
  2138. py[2] = ml1by;
  2139. py[3] = ml2by;
  2140. rtgui_dc_draw_polygon(m->dst, px, py, 4);
  2141. }
  2142. }
  2143. m->last1x = ml1x;
  2144. m->last1y = ml1y;
  2145. m->last2x = ml2x;
  2146. m->last2y = ml2y;
  2147. m->first1x = ml1bx;
  2148. m->first1y = ml1by;
  2149. m->first2x = ml2bx;
  2150. m->first2y = ml2by;
  2151. }
  2152. #define HYPOT(x,y) sqrt((double)(x)*(double)(x)+(double)(y)*(double)(y))
  2153. /*!
  2154. \brief Internal function to to draw wide lines with Murphy algorithm.
  2155. Draws lines parallel to ideal line.
  2156. \param m Pointer to struct for murphy iterator.
  2157. \param x1 X coordinate of first point.
  2158. \param y1 Y coordinate of first point.
  2159. \param x2 X coordinate of second point.
  2160. \param y2 Y coordinate of second point.
  2161. \param width Width of line.
  2162. \param miter Iteration count.
  2163. */
  2164. void _murphyWideline(_MurphyIterator *m, rt_int16_t x1, rt_int16_t y1, rt_int16_t x2, rt_int16_t y2, rt_uint8_t width, rt_uint8_t miter)
  2165. {
  2166. float offset = (float)width / 2.f;
  2167. rt_int16_t temp;
  2168. rt_int16_t ptx, pty, ml1x, ml1y, ml2x, ml2y, ml1bx, ml1by, ml2bx, ml2by;
  2169. int d0, d1; /* difference terms d0=perpendicular to line, d1=along line */
  2170. int q; /* pel counter,q=perpendicular to line */
  2171. int tmp;
  2172. int dd; /* distance along line */
  2173. int tk; /* thickness threshold */
  2174. double ang; /* angle for initial point calculation */
  2175. double sang, cang;
  2176. /* Initialisation */
  2177. m->u = x2 - x1; /* delta x */
  2178. m->v = y2 - y1; /* delta y */
  2179. if (m->u < 0) /* swap to make sure we are in quadrants 1 or 4 */
  2180. {
  2181. temp = x1;
  2182. x1 = x2;
  2183. x2 = temp;
  2184. temp = y1;
  2185. y1 = y2;
  2186. y2 = temp;
  2187. m->u *= -1;
  2188. m->v *= -1;
  2189. }
  2190. if (m->v < 0) /* swap to 1st quadrant and flag */
  2191. {
  2192. m->v *= -1;
  2193. m->quad4 = 1;
  2194. }
  2195. else
  2196. {
  2197. m->quad4 = 0;
  2198. }
  2199. if (m->v > m->u) /* swap things if in 2 octant */
  2200. {
  2201. tmp = m->u;
  2202. m->u = m->v;
  2203. m->v = tmp;
  2204. m->oct2 = 1;
  2205. }
  2206. else
  2207. {
  2208. m->oct2 = 0;
  2209. }
  2210. m->ku = m->u + m->u; /* change in l for square shift */
  2211. m->kv = m->v + m->v; /* change in d for square shift */
  2212. m->kd = m->kv - m->ku; /* change in d for diagonal shift */
  2213. m->kt = m->u - m->kv; /* diag/square decision threshold */
  2214. d0 = 0;
  2215. d1 = 0;
  2216. dd = 0;
  2217. ang = atan((double) m->v / (double) m->u); /* calc new initial point - offset both sides of ideal */
  2218. sang = sin(ang);
  2219. cang = cos(ang);
  2220. if (m->oct2 == 0)
  2221. {
  2222. ptx = x1 + (rt_int16_t)lrint(offset * sang);
  2223. if (m->quad4 == 0)
  2224. {
  2225. pty = y1 - (rt_int16_t)lrint(offset * cang);
  2226. }
  2227. else
  2228. {
  2229. pty = y1 + (rt_int16_t)lrint(offset * cang);
  2230. }
  2231. }
  2232. else
  2233. {
  2234. ptx = x1 - (rt_int16_t)lrint(offset * cang);
  2235. if (m->quad4 == 0)
  2236. {
  2237. pty = y1 + (rt_int16_t)lrint(offset * sang);
  2238. }
  2239. else
  2240. {
  2241. pty = y1 - (rt_int16_t)lrint(offset * sang);
  2242. }
  2243. }
  2244. /* used here for constant thickness line */
  2245. tk = (int) (4. * HYPOT(ptx - x1, pty - y1) * HYPOT(m->u, m->v));
  2246. if (miter == 0)
  2247. {
  2248. m->first1x = -32768;
  2249. m->first1y = -32768;
  2250. m->first2x = -32768;
  2251. m->first2y = -32768;
  2252. m->last1x = -32768;
  2253. m->last1y = -32768;
  2254. m->last2x = -32768;
  2255. m->last2y = -32768;
  2256. }
  2257. for (q = 0; dd <= tk; q++) /* outer loop, stepping perpendicular to line */
  2258. {
  2259. _murphyParaline(m, ptx, pty, d1); /* call to inner loop - right edge */
  2260. if (q == 0)
  2261. {
  2262. ml1x = ptx;
  2263. ml1y = pty;
  2264. ml1bx = m->tempx;
  2265. ml1by = m->tempy;
  2266. }
  2267. else
  2268. {
  2269. ml2x = ptx;
  2270. ml2y = pty;
  2271. ml2bx = m->tempx;
  2272. ml2by = m->tempy;
  2273. }
  2274. if (d0 < m->kt) /* square move */
  2275. {
  2276. if (m->oct2 == 0)
  2277. {
  2278. if (m->quad4 == 0)
  2279. {
  2280. pty++;
  2281. }
  2282. else
  2283. {
  2284. pty--;
  2285. }
  2286. }
  2287. else
  2288. {
  2289. ptx++;
  2290. }
  2291. }
  2292. else /* diagonal move */
  2293. {
  2294. dd += m->kv;
  2295. d0 -= m->ku;
  2296. if (d1 < m->kt) /* normal diagonal */
  2297. {
  2298. if (m->oct2 == 0)
  2299. {
  2300. ptx--;
  2301. if (m->quad4 == 0)
  2302. {
  2303. pty++;
  2304. }
  2305. else
  2306. {
  2307. pty--;
  2308. }
  2309. }
  2310. else
  2311. {
  2312. ptx++;
  2313. if (m->quad4 == 0)
  2314. {
  2315. pty--;
  2316. }
  2317. else
  2318. {
  2319. pty++;
  2320. }
  2321. }
  2322. d1 += m->kv;
  2323. }
  2324. else /* double square move, extra parallel line */
  2325. {
  2326. if (m->oct2 == 0)
  2327. {
  2328. ptx--;
  2329. }
  2330. else
  2331. {
  2332. if (m->quad4 == 0)
  2333. {
  2334. pty--;
  2335. }
  2336. else
  2337. {
  2338. pty++;
  2339. }
  2340. }
  2341. d1 += m->kd;
  2342. if (dd > tk)
  2343. {
  2344. _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
  2345. return; /* breakout on the extra line */
  2346. }
  2347. _murphyParaline(m, ptx, pty, d1);
  2348. if (m->oct2 == 0)
  2349. {
  2350. if (m->quad4 == 0)
  2351. {
  2352. pty++;
  2353. }
  2354. else
  2355. {
  2356. pty--;
  2357. }
  2358. }
  2359. else
  2360. {
  2361. ptx++;
  2362. }
  2363. }
  2364. }
  2365. dd += m->ku;
  2366. d0 += m->kv;
  2367. }
  2368. _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
  2369. }
  2370. /*!
  2371. \brief Draw a thick line with alpha blending.
  2372. \param dst The surface to draw on.
  2373. \param x1 X coordinate of the first point of the line.
  2374. \param y1 Y coordinate of the first point of the line.
  2375. \param x2 X coordinate of the second point of the line.
  2376. \param y2 Y coordinate of the second point of the line.
  2377. \param width Width of the line in pixels. Must be >0.
  2378. \param color The color value of the line to draw (0xRRGGBBAA).
  2379. \returns Returns 0 on success, -1 on failure.
  2380. */
  2381. int rtgui_dc_draw_thick_line(struct rtgui_dc * dst, rt_int16_t x1, rt_int16_t y1, rt_int16_t x2, rt_int16_t y2, rt_uint8_t width)
  2382. {
  2383. int wh;
  2384. _MurphyIterator m;
  2385. if (dst == NULL) return -1;
  2386. if (width < 1) return -1;
  2387. /* Special case: thick "point" */
  2388. if ((x1 == x2) && (y1 == y2))
  2389. {
  2390. struct rtgui_rect rect;
  2391. wh = width / 2;
  2392. rtgui_rect_init(&rect, x1 - wh, y1 - wh, x2 + width, y2 + width);
  2393. rtgui_dc_fill_rect(dst, &rect);
  2394. }
  2395. m.dst = dst;
  2396. m.color = RTGUI_DC_FC(dst);
  2397. _murphyWideline(&m, x1, y1, x2, y2, width, 0);
  2398. _murphyWideline(&m, x1, y1, x2, y2, width, 1);
  2399. return(0);
  2400. }
  2401. RTM_EXPORT(rtgui_dc_draw_thick_line);