123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715 |
- /*
- * File : dc_blend.c
- * This file is part of RT-Thread GUI Engine
- * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Change Logs:
- * Date Author Notes
- * 2013-10-04 Bernard porting SDL software render to RT-Thread GUI
- * 2014-05-06 Bernard Add the SDL2_gfx copyright for aa_ecllipse/
- * thick_line etc.
- */
- /*
- Simple DirectMedia Layer
- Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- /*
- SDL2_gfx: graphics primitives for SDL
- Copyright (C) 2012 Andreas Schiffler
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source
- distribution.
- Andreas Schiffler -- aschiffler at ferzkopp dot net
- */
- #include <rtgui/dc.h>
- #include <rtgui/dc_draw.h>
- #include <rtgui/color.h>
- #include <string.h>
- #include <math.h>
- #include <stdlib.h>
- #define hw_driver (rtgui_graphic_driver_get_default())
- #define _int_swap(x, y) do {x ^= y; y ^= x; x ^= y;} while (0)
- rt_inline rt_uint8_t _dc_get_bits_per_pixel(struct rtgui_dc* dc)
- {
- rt_uint8_t bits_per_pixel = 0;
- if (dc->type == RTGUI_DC_HW || dc->type == RTGUI_DC_CLIENT)
- bits_per_pixel = hw_driver->bits_per_pixel;
- else if (dc->type == RTGUI_DC_BUFFER)
- {
- struct rtgui_dc_buffer *buffer = (struct rtgui_dc_buffer*)dc;
- bits_per_pixel = rtgui_color_get_bits(buffer->pixel_format);
- }
- return bits_per_pixel;
- }
- rt_inline rt_uint16_t _dc_get_pitch(struct rtgui_dc* dc)
- {
- rt_uint16_t pitch = 0;
- if (dc->type == RTGUI_DC_HW || dc->type == RTGUI_DC_CLIENT)
- pitch = hw_driver->pitch;
- else if (dc->type == RTGUI_DC_BUFFER)
- {
- struct rtgui_dc_buffer *dc_buffer;
- dc_buffer = (struct rtgui_dc_buffer*)dc;
- pitch = dc_buffer->pitch;
- }
- return pitch;
- }
- rt_inline rt_uint8_t* _dc_get_pixel(struct rtgui_dc* dc, int x, int y)
- {
- rt_uint8_t *pixel = RT_NULL;
- if ((dc->type == RTGUI_DC_HW) || (dc->type == RTGUI_DC_CLIENT))
- {
- pixel = (rt_uint8_t*)(hw_driver->framebuffer);
- if (pixel == RT_NULL) return RT_NULL;
- pixel = pixel + y * hw_driver->pitch + x * (_UI_BITBYTES(hw_driver->bits_per_pixel));
- }
- else if (dc->type == RTGUI_DC_BUFFER)
- {
- struct rtgui_dc_buffer *dc_buffer;
- dc_buffer = (struct rtgui_dc_buffer*)dc;
- pixel = dc_buffer->pixel + y * dc_buffer->pitch +
- x * rtgui_color_get_bpp(dc_buffer->pixel_format);
- }
- return pixel;
- }
- /* Use the Cohen-Sutherland algorithm for line clipping */
- #define CODE_BOTTOM 1
- #define CODE_TOP 2
- #define CODE_LEFT 4
- #define CODE_RIGHT 8
- static int ComputeOutCode(const rtgui_rect_t * rect, int x, int y)
- {
- int code = 0;
- if (y < rect->y1)
- {
- code |= CODE_TOP;
- }
- else if (y > rect->y2)
- {
- code |= CODE_BOTTOM;
- }
- if (x < rect->x1)
- {
- code |= CODE_LEFT;
- }
- else if (x > rect->x2)
- {
- code |= CODE_RIGHT;
- }
- return code;
- }
- static rt_bool_t _intersect_rect_line(const rtgui_rect_t* rect,
- int *X1, int *Y1,
- int *X2, int *Y2)
- {
- int x = 0;
- int y = 0;
- int x1, y1;
- int x2, y2;
- int rectx1;
- int recty1;
- int rectx2;
- int recty2;
- int outcode1, outcode2;
- x1 = *X1;
- y1 = *Y1;
- x2 = *X2;
- y2 = *Y2;
- rectx1 = rect->x1;
- recty1 = rect->y1;
- rectx2 = rect->x2 - 1;
- recty2 = rect->y2 - 1;
- /* Check to see if entire line is inside rect */
- if (x1 >= rectx1 && x1 <= rectx2 && x2 >= rectx1 && x2 <= rectx2 &&
- y1 >= recty1 && y1 <= recty2 && y2 >= recty1 && y2 <= recty2)
- {
- return RT_TRUE;
- }
- /* Check to see if entire line is to one side of rect */
- if ((x1 < rectx1 && x2 < rectx1) || (x1 > rectx2 && x2 > rectx2) ||
- (y1 < recty1 && y2 < recty1) || (y1 > recty2 && y2 > recty2))
- {
- return RT_FALSE;
- }
- if (y1 == y2)
- {
- /* Horizontal line, easy to clip */
- if (x1 < rectx1)
- {
- *X1 = rectx1;
- }
- else if (x1 > rectx2)
- {
- *X1 = rectx2;
- }
- if (x2 < rectx1)
- {
- *X2 = rectx1;
- }
- else if (x2 > rectx2)
- {
- *X2 = rectx2;
- }
- return RT_TRUE;
- }
- if (x1 == x2)
- {
- /* Vertical line, easy to clip */
- if (y1 < recty1)
- {
- *Y1 = recty1;
- }
- else if (y1 > recty2)
- {
- *Y1 = recty2;
- }
- if (y2 < recty1)
- {
- *Y2 = recty1;
- }
- else if (y2 > recty2)
- {
- *Y2 = recty2;
- }
- return RT_TRUE;
- }
- /* More complicated Cohen-Sutherland algorithm */
- outcode1 = ComputeOutCode(rect, x1, y1);
- outcode2 = ComputeOutCode(rect, x2, y2);
- while (outcode1 || outcode2)
- {
- if (outcode1 & outcode2)
- {
- return RT_FALSE;
- }
- if (outcode1)
- {
- if (outcode1 & CODE_TOP)
- {
- y = recty1;
- x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
- }
- else if (outcode1 & CODE_BOTTOM)
- {
- y = recty2;
- x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
- }
- else if (outcode1 & CODE_LEFT)
- {
- x = rectx1;
- y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
- }
- else if (outcode1 & CODE_RIGHT)
- {
- x = rectx2;
- y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
- }
- x1 = x;
- y1 = y;
- outcode1 = ComputeOutCode(rect, x, y);
- }
- else
- {
- if (outcode2 & CODE_TOP)
- {
- y = recty1;
- x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
- }
- else if (outcode2 & CODE_BOTTOM)
- {
- y = recty2;
- x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
- }
- else if (outcode2 & CODE_LEFT)
- {
- x = rectx1;
- y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
- }
- else if (outcode2 & CODE_RIGHT)
- {
- x = rectx2;
- y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
- }
- x2 = x;
- y2 = y;
- outcode2 = ComputeOutCode(rect, x, y);
- }
- }
- *X1 = x1;
- *Y1 = y1;
- *X2 = x2;
- *Y2 = y2;
- return RT_TRUE;
- }
- static void
- _dc_draw_line1(struct rtgui_dc * dst, int x1, int y1, int x2, int y2, rtgui_color_t color,
- rt_bool_t draw_end)
- {
- if (y1 == y2)
- {
- int length;
- rt_uint8_t *pixel;
- if (x1 <= x2)
- {
- pixel = (rt_uint8_t *)_dc_get_pixel(dst, x1, y1);
- length = draw_end ? (x2-x1+1) : (x2-x1);
- }
- else
- {
- pixel = (rt_uint8_t *)_dc_get_pixel(dst, x2, y1);
- if (!draw_end)
- {
- ++pixel;
- }
- length = draw_end ? (x1-x2+1) : (x1-x2);
- }
- rt_memset(pixel, color, length);
- }
- else if (x1 == x2)
- {
- VLINE(rt_uint8_t, DRAW_FASTSETPIXEL1, draw_end);
- }
- else if (ABS(x1 - x2) == ABS(y1 - y2))
- {
- DLINE(rt_uint8_t, DRAW_FASTSETPIXEL1, draw_end);
- }
- else
- {
- BLINE(x1, y1, x2, y2, DRAW_FASTSETPIXELXY1, draw_end);
- }
- }
- static void
- _dc_draw_line2(struct rtgui_dc * dst, int x1, int y1, int x2, int y2, rtgui_color_t c,
- rt_bool_t draw_end)
- {
- rt_uint16_t color;
- if (rtgui_dc_get_pixel_format(dst) == RTGRAPHIC_PIXEL_FORMAT_RGB565)
- color = rtgui_color_to_565(c);
- else
- color = rtgui_color_to_565p(c);
- if (y1 == y2)
- {
- HLINE(rt_uint16_t, DRAW_FASTSETPIXEL2, draw_end);
- }
- else if (x1 == x2)
- {
- VLINE(rt_uint16_t, DRAW_FASTSETPIXEL2, draw_end);
- }
- else if (ABS(x1 - x2) == ABS(y1 - y2))
- {
- DLINE(rt_uint16_t, DRAW_FASTSETPIXEL2, draw_end);
- }
- else
- {
- rt_uint8_t _r, _g, _b, _a;
- _r = RTGUI_RGB_R(c);
- _g = RTGUI_RGB_G(c);
- _b = RTGUI_RGB_B(c);
- _a = RTGUI_RGB_A(c);
- if (rtgui_dc_get_pixel_format(dst) == RTGRAPHIC_PIXEL_FORMAT_RGB565)
- {
- AALINE(x1, y1, x2, y2,
- DRAW_FASTSETPIXELXY2, DRAW_SETPIXELXY_BLEND_RGB565,
- draw_end);
- }
- else if (rtgui_dc_get_pixel_format(dst) == RTGRAPHIC_PIXEL_FORMAT_BGR565)
- {
- AALINE(x1, y1, x2, y2,
- DRAW_FASTSETPIXELXY2, DRAW_SETPIXELXY_BLEND_BGR565,
- draw_end);
- }
- }
- }
- static void
- _dc_draw_line4(struct rtgui_dc * dst, int x1, int y1, int x2, int y2, rtgui_color_t color,
- rt_bool_t draw_end)
- {
- if (y1 == y2)
- {
- HLINE(rt_uint32_t, DRAW_FASTSETPIXEL4, draw_end);
- }
- else if (x1 == x2)
- {
- VLINE(rt_uint32_t, DRAW_FASTSETPIXEL4, draw_end);
- }
- else if (ABS(x1 - x2) == ABS(y1 - y2))
- {
- DLINE(rt_uint32_t, DRAW_FASTSETPIXEL4, draw_end);
- }
- else
- {
- rt_uint8_t _r, _g, _b, _a;
- _r = RTGUI_RGB_R(color);
- _g = RTGUI_RGB_G(color);
- _b = RTGUI_RGB_B(color);
- _a = RTGUI_RGB_A(color);
- if (rtgui_dc_get_pixel_format(dst) == RTGRAPHIC_PIXEL_FORMAT_RGB888)
- {
- AALINE(x1, y1, x2, y2,
- DRAW_FASTSETPIXELXY4, DRAW_SETPIXELXY_BLEND_RGB888,
- draw_end);
- }
- else if (rtgui_dc_get_pixel_format(dst) == RTGRAPHIC_PIXEL_FORMAT_ARGB888)
- {
- AALINE(x1, y1, x2, y2,
- DRAW_FASTSETPIXELXY4, DRAW_SETPIXELXY_BLEND_ARGB8888,
- draw_end);
- }
- }
- }
- typedef void (*DrawLineFunc) (struct rtgui_dc * dst,
- int x1, int y1, int x2, int y2,
- rtgui_color_t color, rt_bool_t draw_end);
- static DrawLineFunc
- _dc_calc_draw_line_func(int bpp)
- {
- switch (bpp)
- {
- case 1:
- return _dc_draw_line1;
- case 2:
- return _dc_draw_line2;
- case 4:
- return _dc_draw_line4;
- }
- return NULL;
- }
- static void _do_draw_line(struct rtgui_dc * dst,
- rtgui_color_t color,
- int x1, int y1,
- int x2, int y2,
- rt_bool_t draw_end)
- {
- int bpp;
- DrawLineFunc func;
- bpp = _dc_get_bits_per_pixel(dst);
- if (bpp < 8)
- return;
- func = _dc_calc_draw_line_func(bpp/8);
- if (!func)
- {
- rt_kprintf("dc_draw_line(): Unsupported pixel format\n");
- return;
- }
- /* perform clip */
- if (dst->type == RTGUI_DC_CLIENT)
- {
- rtgui_widget_t *owner;
- /* get owner */
- owner = RTGUI_CONTAINER_OF(dst, struct rtgui_widget, dc_type);
- x1 = x1 + owner->extent.x1;
- x2 = x2 + owner->extent.x1;
- y1 = y1 + owner->extent.y1;
- y2 = y2 + owner->extent.y1;
- if (owner->clip.data == RT_NULL)
- {
- rtgui_rect_t *prect;
- /* no clip */
- prect = &(owner->clip.extents);
- /* calculate line intersect */
- if (_intersect_rect_line(prect, &x1, &y1, &x2, &y2) == RT_FALSE)
- return;
- /* draw line */
- func(dst, x1, y1, x2, y2, color, draw_end);
- }
- else
- {
- register rt_base_t index;
- for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++)
- {
- rtgui_rect_t *prect;
- int draw_x1, draw_x2;
- int draw_y1, draw_y2;
- prect = ((rtgui_rect_t *)(owner->clip.data + index + 1));
- draw_x1 = x1;
- draw_x2 = x2;
- draw_y1 = y1;
- draw_y2 = y2;
- /* calculate line intersect */
- if (_intersect_rect_line(prect, &draw_x1, &draw_y1, &draw_x2, &draw_y2) == RT_FALSE)
- continue;
- /* draw line */
- func(dst, draw_x1, draw_y1, draw_x2, draw_y2, color, draw_end);
- }
- }
- }
- else
- {
- if (dst->type == RTGUI_DC_HW)
- {
- rtgui_widget_t *owner;
- rtgui_rect_t *prect;
- /* no clip */
- struct rtgui_dc_hw *dc_hw = (struct rtgui_dc_hw*)dst;
- owner = dc_hw->owner;
- x1 = x1 + owner->extent.x1;
- x2 = x2 + owner->extent.x1;
- y1 = y1 + owner->extent.y1;
- y2 = y2 + owner->extent.y1;
- prect = &(owner->clip.extents);
- if (_intersect_rect_line(prect, &x1, &y1, &x2, &y2) == RT_FALSE)
- return;
- }
- else if (dst->type == RTGUI_DC_BUFFER)
- {
- rtgui_rect_t rect;
- struct rtgui_dc_buffer *pbf = (struct rtgui_dc_buffer *)dst;
- rect.x1 = rect.y1 = 0;
- rect.x2 = pbf->width;
- rect.y2 = pbf->height;
- if (_intersect_rect_line(&rect, &x1, &y1, &x2, &y2) == RT_FALSE)
- return;
- }
- func(dst, x1, y1, x2, y2, color, draw_end);
- }
- }
- void rtgui_dc_draw_aa_line(struct rtgui_dc * dst, int x1, int y1, int x2, int y2)
- {
- rtgui_color_t color;
- RT_ASSERT(dst != RT_NULL);
- if (!rtgui_dc_get_visible(dst))
- return;
- /* we do not support pixel DC */
- if (_dc_get_pixel(dst, 0, 0) == RT_NULL)
- return;
- color = rtgui_dc_get_gc(dst)->foreground;
- _do_draw_line(dst, color, x1, y1, x2, y2, RT_FALSE);
- }
- RTM_EXPORT(rtgui_dc_draw_aa_line);
- void rtgui_dc_draw_aa_lines(struct rtgui_dc * dst, const struct rtgui_point * points, int count)
- {
- int i;
- int x1, y1;
- int x2, y2;
- rtgui_color_t color;
- RT_ASSERT(dst);
- if (!rtgui_dc_get_visible(dst))
- return;
- /* we do not support pixel DC */
- if (_dc_get_pixel(dst, 0, 0) == RT_NULL)
- return;
- color = rtgui_dc_get_gc(dst)->foreground;
- for (i = 1; i < count; ++i)
- {
- rt_bool_t draw_end;
- x1 = points[i-1].x;
- y1 = points[i-1].y;
- x2 = points[i].x;
- y2 = points[i].y;
- /* Draw the end if it was clipped */
- draw_end = (x2 != points[i].x || y2 != points[i].y);
- _do_draw_line(dst, color, x1, y1, x2, y2, draw_end);
- }
- if (points[0].x != points[count-1].x || points[0].y != points[count-1].y)
- {
- rtgui_dc_draw_point(dst, points[count-1].x, points[count-1].y);
- }
- return ;
- }
- static int
- _dc_blend_point_rgb565(struct rtgui_dc * dst, int x, int y, enum RTGUI_BLENDMODE blendMode, rt_uint8_t r,
- rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
- {
- unsigned inva = 0xff - a;
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- DRAW_SETPIXELXY_BLEND_RGB565(x, y);
- break;
- case RTGUI_BLENDMODE_ADD:
- DRAW_SETPIXELXY_ADD_RGB565(x, y);
- break;
- case RTGUI_BLENDMODE_MOD:
- DRAW_SETPIXELXY_MOD_RGB565(x, y);
- break;
- default:
- DRAW_SETPIXELXY_RGB565(x, y);
- break;
- }
- return 0;
- }
- static int
- _dc_blend_point_bgr565(struct rtgui_dc * dst, int x, int y, enum RTGUI_BLENDMODE blendMode, rt_uint8_t r,
- rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
- {
- unsigned inva = 0xff - a;
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- DRAW_SETPIXELXY_BLEND_BGR565(x, y);
- break;
- case RTGUI_BLENDMODE_ADD:
- DRAW_SETPIXELXY_ADD_BGR565(x, y);
- break;
- case RTGUI_BLENDMODE_MOD:
- DRAW_SETPIXELXY_MOD_BGR565(x, y);
- break;
- default:
- DRAW_SETPIXELXY_BGR565(x, y);
- break;
- }
- return 0;
- }
- static int
- _dc_blend_point_rgb888(struct rtgui_dc * dst, int x, int y, enum RTGUI_BLENDMODE blendMode, rt_uint8_t r,
- rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
- {
- unsigned inva = 0xff - a;
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- DRAW_SETPIXELXY_BLEND_RGB888(x, y);
- break;
- case RTGUI_BLENDMODE_ADD:
- DRAW_SETPIXELXY_ADD_RGB888(x, y);
- break;
- case RTGUI_BLENDMODE_MOD:
- DRAW_SETPIXELXY_MOD_RGB888(x, y);
- break;
- default:
- DRAW_SETPIXELXY_RGB888(x, y);
- break;
- }
- return 0;
- }
- static int
- _dc_blend_point_argb8888(struct rtgui_dc * dst, int x, int y, enum RTGUI_BLENDMODE blendMode,
- rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
- {
- unsigned inva = 0xff - a;
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- DRAW_SETPIXELXY_BLEND_ARGB8888(x, y);
- break;
- case RTGUI_BLENDMODE_ADD:
- DRAW_SETPIXELXY_ADD_ARGB8888(x, y);
- break;
- case RTGUI_BLENDMODE_MOD:
- DRAW_SETPIXELXY_MOD_ARGB8888(x, y);
- break;
- default:
- DRAW_SETPIXELXY_ARGB8888(x, y);
- break;
- }
- return 0;
- }
- void
- rtgui_dc_blend_point(struct rtgui_dc * dst, int x, int y, enum RTGUI_BLENDMODE blendMode, rt_uint8_t r,
- rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
- {
- RT_ASSERT(dst != RT_NULL);
- /* Negative coordinates are always invisible. */
- if (x < 0 || y < 0)
- return;
- if (!rtgui_dc_get_visible(dst)) return;
- /* we do not support pixel DC */
- if (_dc_get_pixel(dst, 0, 0) == RT_NULL) return;
- /* Perform clipping */
- if (dst->type == RTGUI_DC_CLIENT)
- {
- rtgui_widget_t *owner;
- rtgui_rect_t rect;
- /* get owner */
- owner = RTGUI_CONTAINER_OF(dst, struct rtgui_widget, dc_type);
- x = x + owner->extent.x1;
- y = y + owner->extent.y1;
- if (rtgui_region_contains_point(&(owner->clip), x, y, &rect) != RT_EOK)
- return ;
- }
- else if (dst->type == RTGUI_DC_HW)
- {
- struct rtgui_dc_hw *dc = (struct rtgui_dc_hw *) dst;
- x = x + dc->owner->extent.x1;
- y = y + dc->owner->extent.y1;
- if (x >= dc->owner->extent.x2)
- return;
- if (y >= dc->owner->extent.y2)
- return;
- }
- else if (dst->type == RTGUI_DC_BUFFER)
- {
- struct rtgui_dc_buffer *dc = (struct rtgui_dc_buffer *) dst;
- if (x >= dc->width || y >= dc->height)
- return;
- }
- if (blendMode == RTGUI_BLENDMODE_BLEND || blendMode == RTGUI_BLENDMODE_ADD)
- {
- r = DRAW_MUL(r, a);
- g = DRAW_MUL(g, a);
- b = DRAW_MUL(b, a);
- }
- switch (rtgui_dc_get_pixel_format(dst))
- {
- case RTGRAPHIC_PIXEL_FORMAT_RGB565:
- _dc_blend_point_rgb565(dst, x, y, blendMode, r, g, b, a);
- break;
- case RTGRAPHIC_PIXEL_FORMAT_BGR565:
- _dc_blend_point_bgr565(dst, x, y, blendMode, r, g, b, a);
- break;
- case RTGRAPHIC_PIXEL_FORMAT_RGB888:
- _dc_blend_point_rgb888(dst, x, y, blendMode, r, g, b, a);
- break;
- case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
- _dc_blend_point_argb8888(dst, x, y, blendMode, r, g, b, a);
- break;
- default:
- break;
- }
- }
- RTM_EXPORT(rtgui_dc_blend_point);
- void
- rtgui_dc_blend_points(struct rtgui_dc *dst, const rtgui_point_t *points, int count,
- enum RTGUI_BLENDMODE blendMode, rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
- {
- int i;
- int x, y;
- int (*func)(struct rtgui_dc * dst, int x, int y,
- enum RTGUI_BLENDMODE blendMode, rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a) = NULL;
- RT_ASSERT(dst != RT_NULL);
- if (!rtgui_dc_get_visible(dst)) return;
- /* we do not support pixel DC */
- if (_dc_get_pixel(dst, 0, 0) == RT_NULL) return;
- if (blendMode == RTGUI_BLENDMODE_BLEND || blendMode == RTGUI_BLENDMODE_ADD)
- {
- r = DRAW_MUL(r, a);
- g = DRAW_MUL(g, a);
- b = DRAW_MUL(b, a);
- }
- /* FIXME: Does this function pointer slow things down significantly? */
- switch (rtgui_dc_get_pixel_format(dst))
- {
- case RTGRAPHIC_PIXEL_FORMAT_RGB565:
- func = _dc_blend_point_rgb565;
- break;
- case RTGRAPHIC_PIXEL_FORMAT_RGB888:
- func = _dc_blend_point_rgb888;
- break;
- case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
- func = _dc_blend_point_argb8888;
- default:
- return;
- }
- /* get owner */
- if (dst->type == RTGUI_DC_CLIENT)
- {
- rtgui_widget_t *owner;
- rtgui_rect_t rect;
- owner = RTGUI_CONTAINER_OF(dst, struct rtgui_widget, dc_type);
- for (i = 0; i < count; ++i)
- {
- x = points[i].x;
- y = points[i].y;
- /* Perform clipping */
- x = x + owner->extent.x1;
- y = y + owner->extent.y1;
- if (rtgui_region_contains_point(&(owner->clip), x, y, &rect) != RT_EOK)
- continue;
- func(dst, x, y, blendMode, r, g, b, a);
- }
- }
- else if (dst->type == RTGUI_DC_HW)
- {
- struct rtgui_dc_hw *dc = (struct rtgui_dc_hw *) dst;
- for (i = 0; i < count; ++i)
- {
- x = points[i].x;
- y = points[i].y;
- x = x + dc->owner->extent.x1;
- y = y + dc->owner->extent.y1;
- if (x > dc->owner->extent.x2) return;
- if (y > dc->owner->extent.y2) return;
- func(dst, x, y, blendMode, r, g, b, a);
- }
- }
- else
- {
- for (i = 0; i < count; ++i)
- {
- x = points[i].x;
- y = points[i].y;
- func(dst, x, y, blendMode, r, g, b, a);
- }
- }
- }
- RTM_EXPORT(rtgui_dc_blend_points);
- static void
- _dc_blend_line_rgb565(struct rtgui_dc * dst, int x1, int y1, int x2, int y2,
- enum RTGUI_BLENDMODE blendMode, rt_uint8_t _r, rt_uint8_t _g, rt_uint8_t _b, rt_uint8_t _a,
- rt_bool_t draw_end)
- {
- unsigned r, g, b, a, inva;
- if (blendMode == RTGUI_BLENDMODE_BLEND || blendMode == RTGUI_BLENDMODE_ADD)
- {
- r = DRAW_MUL(_r, _a);
- g = DRAW_MUL(_g, _a);
- b = DRAW_MUL(_b, _a);
- a = _a;
- }
- else
- {
- r = _r;
- g = _g;
- b = _b;
- a = _a;
- }
- inva = (a ^ 0xff);
- if (y1 == y2)
- {
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- HLINE(rt_uint16_t, DRAW_SETPIXEL_BLEND_RGB565, draw_end);
- break;
- case RTGUI_BLENDMODE_ADD:
- HLINE(rt_uint16_t, DRAW_SETPIXEL_ADD_RGB565, draw_end);
- break;
- case RTGUI_BLENDMODE_MOD:
- HLINE(rt_uint16_t, DRAW_SETPIXEL_MOD_RGB565, draw_end);
- break;
- default:
- HLINE(rt_uint16_t, DRAW_SETPIXEL_RGB565, draw_end);
- break;
- }
- }
- else if (x1 == x2)
- {
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- VLINE(rt_uint16_t, DRAW_SETPIXEL_BLEND_RGB565, draw_end);
- break;
- case RTGUI_BLENDMODE_ADD:
- VLINE(rt_uint16_t, DRAW_SETPIXEL_ADD_RGB565, draw_end);
- break;
- case RTGUI_BLENDMODE_MOD:
- VLINE(rt_uint16_t, DRAW_SETPIXEL_MOD_RGB565, draw_end);
- break;
- default:
- VLINE(rt_uint16_t, DRAW_SETPIXEL_RGB565, draw_end);
- break;
- }
- }
- else if (ABS(x1 - x2) == ABS(y1 - y2))
- {
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- DLINE(rt_uint16_t, DRAW_SETPIXEL_BLEND_RGB565, draw_end);
- break;
- case RTGUI_BLENDMODE_ADD:
- DLINE(rt_uint16_t, DRAW_SETPIXEL_ADD_RGB565, draw_end);
- break;
- case RTGUI_BLENDMODE_MOD:
- DLINE(rt_uint16_t, DRAW_SETPIXEL_MOD_RGB565, draw_end);
- break;
- default:
- DLINE(rt_uint16_t, DRAW_SETPIXEL_RGB565, draw_end);
- break;
- }
- }
- else
- {
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- AALINE(x1, y1, x2, y2,
- DRAW_SETPIXELXY_BLEND_RGB565, DRAW_SETPIXELXY_BLEND_RGB565,
- draw_end);
- break;
- case RTGUI_BLENDMODE_ADD:
- AALINE(x1, y1, x2, y2,
- DRAW_SETPIXELXY_ADD_RGB565, DRAW_SETPIXELXY_ADD_RGB565,
- draw_end);
- break;
- case RTGUI_BLENDMODE_MOD:
- AALINE(x1, y1, x2, y2,
- DRAW_SETPIXELXY_MOD_RGB565, DRAW_SETPIXELXY_MOD_RGB565,
- draw_end);
- break;
- default:
- AALINE(x1, y1, x2, y2,
- DRAW_SETPIXELXY_RGB565, DRAW_SETPIXELXY_BLEND_RGB565,
- draw_end);
- break;
- }
- }
- }
- static void
- _dc_blend_line_bgr565(struct rtgui_dc * dst, int x1, int y1, int x2, int y2,
- enum RTGUI_BLENDMODE blendMode, rt_uint8_t _r, rt_uint8_t _g, rt_uint8_t _b, rt_uint8_t _a,
- rt_bool_t draw_end)
- {
- unsigned r, g, b, a, inva;
- if (blendMode == RTGUI_BLENDMODE_BLEND || blendMode == RTGUI_BLENDMODE_ADD)
- {
- r = DRAW_MUL(_r, _a);
- g = DRAW_MUL(_g, _a);
- b = DRAW_MUL(_b, _a);
- a = _a;
- }
- else
- {
- r = _r;
- g = _g;
- b = _b;
- a = _a;
- }
- inva = (a ^ 0xff);
- if (y1 == y2)
- {
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- HLINE(rt_uint16_t, DRAW_SETPIXEL_BLEND_BGR565, draw_end);
- break;
- case RTGUI_BLENDMODE_ADD:
- HLINE(rt_uint16_t, DRAW_SETPIXEL_ADD_BGR565, draw_end);
- break;
- case RTGUI_BLENDMODE_MOD:
- HLINE(rt_uint16_t, DRAW_SETPIXEL_MOD_BGR565, draw_end);
- break;
- default:
- HLINE(rt_uint16_t, DRAW_SETPIXEL_BGR565, draw_end);
- break;
- }
- }
- else if (x1 == x2)
- {
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- VLINE(rt_uint16_t, DRAW_SETPIXEL_BLEND_BGR565, draw_end);
- break;
- case RTGUI_BLENDMODE_ADD:
- VLINE(rt_uint16_t, DRAW_SETPIXEL_ADD_BGR565, draw_end);
- break;
- case RTGUI_BLENDMODE_MOD:
- VLINE(rt_uint16_t, DRAW_SETPIXEL_MOD_BGR565, draw_end);
- break;
- default:
- VLINE(rt_uint16_t, DRAW_SETPIXEL_BGR565, draw_end);
- break;
- }
- }
- else if (ABS(x1 - x2) == ABS(y1 - y2))
- {
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- DLINE(rt_uint16_t, DRAW_SETPIXEL_BLEND_BGR565, draw_end);
- break;
- case RTGUI_BLENDMODE_ADD:
- DLINE(rt_uint16_t, DRAW_SETPIXEL_ADD_BGR565, draw_end);
- break;
- case RTGUI_BLENDMODE_MOD:
- DLINE(rt_uint16_t, DRAW_SETPIXEL_MOD_BGR565, draw_end);
- break;
- default:
- DLINE(rt_uint16_t, DRAW_SETPIXEL_BGR565, draw_end);
- break;
- }
- }
- else
- {
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- AALINE(x1, y1, x2, y2,
- DRAW_SETPIXELXY_BLEND_BGR565, DRAW_SETPIXELXY_BLEND_BGR565,
- draw_end);
- break;
- case RTGUI_BLENDMODE_ADD:
- AALINE(x1, y1, x2, y2,
- DRAW_SETPIXELXY_ADD_BGR565, DRAW_SETPIXELXY_ADD_BGR565,
- draw_end);
- break;
- case RTGUI_BLENDMODE_MOD:
- AALINE(x1, y1, x2, y2,
- DRAW_SETPIXELXY_MOD_BGR565, DRAW_SETPIXELXY_MOD_BGR565,
- draw_end);
- break;
- default:
- AALINE(x1, y1, x2, y2,
- DRAW_SETPIXELXY_BGR565, DRAW_SETPIXELXY_BLEND_BGR565,
- draw_end);
- break;
- }
- }
- }
- static void
- _dc_blend_line_rgb888(struct rtgui_dc * dst, int x1, int y1, int x2, int y2,
- enum RTGUI_BLENDMODE blendMode, rt_uint8_t _r, rt_uint8_t _g, rt_uint8_t _b, rt_uint8_t _a,
- rt_bool_t draw_end)
- {
- unsigned r, g, b, a, inva;
- if (blendMode == RTGUI_BLENDMODE_BLEND || blendMode == RTGUI_BLENDMODE_ADD)
- {
- r = DRAW_MUL(_r, _a);
- g = DRAW_MUL(_g, _a);
- b = DRAW_MUL(_b, _a);
- a = _a;
- }
- else
- {
- r = _r;
- g = _g;
- b = _b;
- a = _a;
- }
- inva = (a ^ 0xff);
- if (y1 == y2)
- {
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- HLINE(rt_uint32_t, DRAW_SETPIXEL_BLEND_RGB888, draw_end);
- break;
- case RTGUI_BLENDMODE_ADD:
- HLINE(rt_uint32_t, DRAW_SETPIXEL_ADD_RGB888, draw_end);
- break;
- case RTGUI_BLENDMODE_MOD:
- HLINE(rt_uint32_t, DRAW_SETPIXEL_MOD_RGB888, draw_end);
- break;
- default:
- HLINE(rt_uint32_t, DRAW_SETPIXEL_RGB888, draw_end);
- break;
- }
- }
- else if (x1 == x2)
- {
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- VLINE(rt_uint32_t, DRAW_SETPIXEL_BLEND_RGB888, draw_end);
- break;
- case RTGUI_BLENDMODE_ADD:
- VLINE(rt_uint32_t, DRAW_SETPIXEL_ADD_RGB888, draw_end);
- break;
- case RTGUI_BLENDMODE_MOD:
- VLINE(rt_uint32_t, DRAW_SETPIXEL_MOD_RGB888, draw_end);
- break;
- default:
- VLINE(rt_uint32_t, DRAW_SETPIXEL_RGB888, draw_end);
- break;
- }
- }
- else if (ABS(x1 - x2) == ABS(y1 - y2))
- {
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- DLINE(rt_uint32_t, DRAW_SETPIXEL_BLEND_RGB888, draw_end);
- break;
- case RTGUI_BLENDMODE_ADD:
- DLINE(rt_uint32_t, DRAW_SETPIXEL_ADD_RGB888, draw_end);
- break;
- case RTGUI_BLENDMODE_MOD:
- DLINE(rt_uint32_t, DRAW_SETPIXEL_MOD_RGB888, draw_end);
- break;
- default:
- DLINE(rt_uint32_t, DRAW_SETPIXEL_RGB888, draw_end);
- break;
- }
- }
- else
- {
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- AALINE(x1, y1, x2, y2,
- DRAW_SETPIXELXY_BLEND_RGB888, DRAW_SETPIXELXY_BLEND_RGB888,
- draw_end);
- break;
- case RTGUI_BLENDMODE_ADD:
- AALINE(x1, y1, x2, y2,
- DRAW_SETPIXELXY_ADD_RGB888, DRAW_SETPIXELXY_ADD_RGB888,
- draw_end);
- break;
- case RTGUI_BLENDMODE_MOD:
- AALINE(x1, y1, x2, y2,
- DRAW_SETPIXELXY_MOD_RGB888, DRAW_SETPIXELXY_MOD_RGB888,
- draw_end);
- break;
- default:
- AALINE(x1, y1, x2, y2,
- DRAW_SETPIXELXY_RGB888, DRAW_SETPIXELXY_BLEND_RGB888,
- draw_end);
- break;
- }
- }
- }
- static void
- _dc_blend_line_argb8888(struct rtgui_dc * dst, int x1, int y1, int x2, int y2,
- enum RTGUI_BLENDMODE blendMode, rt_uint8_t _r, rt_uint8_t _g, rt_uint8_t _b, rt_uint8_t _a,
- rt_bool_t draw_end)
- {
- unsigned r, g, b, a, inva;
- if (blendMode == RTGUI_BLENDMODE_BLEND || blendMode == RTGUI_BLENDMODE_ADD)
- {
- r = DRAW_MUL(_r, _a);
- g = DRAW_MUL(_g, _a);
- b = DRAW_MUL(_b, _a);
- a = _a;
- }
- else
- {
- r = _r;
- g = _g;
- b = _b;
- a = _a;
- }
- inva = (a ^ 0xff);
- if (y1 == y2)
- {
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- HLINE(rt_uint32_t, DRAW_SETPIXEL_BLEND_ARGB8888, draw_end);
- break;
- case RTGUI_BLENDMODE_ADD:
- HLINE(rt_uint32_t, DRAW_SETPIXEL_ADD_ARGB8888, draw_end);
- break;
- case RTGUI_BLENDMODE_MOD:
- HLINE(rt_uint32_t, DRAW_SETPIXEL_MOD_ARGB8888, draw_end);
- break;
- default:
- HLINE(rt_uint32_t, DRAW_SETPIXEL_ARGB8888, draw_end);
- break;
- }
- }
- else if (x1 == x2)
- {
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- VLINE(rt_uint32_t, DRAW_SETPIXEL_BLEND_ARGB8888, draw_end);
- break;
- case RTGUI_BLENDMODE_ADD:
- VLINE(rt_uint32_t, DRAW_SETPIXEL_ADD_ARGB8888, draw_end);
- break;
- case RTGUI_BLENDMODE_MOD:
- VLINE(rt_uint32_t, DRAW_SETPIXEL_MOD_ARGB8888, draw_end);
- break;
- default:
- VLINE(rt_uint32_t, DRAW_SETPIXEL_ARGB8888, draw_end);
- break;
- }
- }
- else if (ABS(x1 - x2) == ABS(y1 - y2))
- {
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- DLINE(rt_uint32_t, DRAW_SETPIXEL_BLEND_ARGB8888, draw_end);
- break;
- case RTGUI_BLENDMODE_ADD:
- DLINE(rt_uint32_t, DRAW_SETPIXEL_ADD_ARGB8888, draw_end);
- break;
- case RTGUI_BLENDMODE_MOD:
- DLINE(rt_uint32_t, DRAW_SETPIXEL_MOD_ARGB8888, draw_end);
- break;
- default:
- DLINE(rt_uint32_t, DRAW_SETPIXEL_ARGB8888, draw_end);
- break;
- }
- }
- else
- {
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- AALINE(x1, y1, x2, y2,
- DRAW_SETPIXELXY_BLEND_ARGB8888, DRAW_SETPIXELXY_BLEND_ARGB8888,
- draw_end);
- break;
- case RTGUI_BLENDMODE_ADD:
- AALINE(x1, y1, x2, y2,
- DRAW_SETPIXELXY_ADD_ARGB8888, DRAW_SETPIXELXY_ADD_ARGB8888,
- draw_end);
- break;
- case RTGUI_BLENDMODE_MOD:
- AALINE(x1, y1, x2, y2,
- DRAW_SETPIXELXY_MOD_ARGB8888, DRAW_SETPIXELXY_MOD_ARGB8888,
- draw_end);
- break;
- default:
- AALINE(x1, y1, x2, y2,
- DRAW_SETPIXELXY_ARGB8888, DRAW_SETPIXELXY_BLEND_ARGB8888,
- draw_end);
- break;
- }
- }
- }
- typedef void (*BlendLineFunc) (struct rtgui_dc * dst,
- int x1, int y1, int x2, int y2,
- enum RTGUI_BLENDMODE blendMode,
- rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a,
- rt_bool_t draw_end);
- static BlendLineFunc
- _dc_calc_blend_line_func(rt_uint8_t pixel_format)
- {
- switch (pixel_format)
- {
- case RTGRAPHIC_PIXEL_FORMAT_RGB565:
- return _dc_blend_line_rgb565;
- case RTGRAPHIC_PIXEL_FORMAT_BGR565:
- return _dc_blend_line_bgr565;
- case RTGRAPHIC_PIXEL_FORMAT_RGB888:
- return _dc_blend_line_rgb888;
- case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
- return _dc_blend_line_argb8888;
- }
- return NULL;
- }
- static void _do_blend_line(struct rtgui_dc * dst,
- rtgui_color_t color,
- int x1, int y1,
- int x2, int y2,
- enum RTGUI_BLENDMODE blendMode,
- rt_bool_t draw_end)
- {
- BlendLineFunc func;
- rt_uint8_t pixel_format;
- rt_uint8_t r, g, b, a;
- rtgui_widget_t *owner;
- pixel_format = rtgui_dc_get_pixel_format(dst);
- func = _dc_calc_blend_line_func(pixel_format);
- if (!func)
- {
- rt_kprintf("dc_blend_line(): Unsupported pixel format\n");
- return;
- }
- r = RTGUI_RGB_R(color);
- g = RTGUI_RGB_G(color);
- b = RTGUI_RGB_B(color);
- a = RTGUI_RGB_A(color);
- /* perform clip */
- if (dst->type == RTGUI_DC_CLIENT)
- {
- /* get owner */
- owner = RTGUI_CONTAINER_OF(dst, struct rtgui_widget, dc_type);
- x1 = x1 + owner->extent.x1;
- x2 = x2 + owner->extent.x1;
- y1 = y1 + owner->extent.y1;
- y2 = y2 + owner->extent.y1;
- if (owner->clip.data == RT_NULL)
- {
- rtgui_rect_t *prect;
- /* no clip */
- prect = &(owner->clip.extents);
- /* calculate line intersect */
- if (_intersect_rect_line(prect, &x1, &y1, &x2, &y2) == RT_FALSE)
- return;
- /* draw line */
- func(dst, x1, y1, x2, y2, blendMode, r, g, b, a, RT_TRUE);
- }
- else
- {
- register rt_base_t index;
- for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++)
- {
- rtgui_rect_t *prect;
- int draw_x1, draw_x2;
- int draw_y1, draw_y2;
- prect = ((rtgui_rect_t *)(owner->clip.data + index + 1));
- draw_x1 = x1;
- draw_x2 = x2;
- draw_y1 = y1;
- draw_y2 = y2;
- /* calculate line intersect */
- if (_intersect_rect_line(prect, &draw_x1, &draw_y1, &draw_x2, &draw_y2) == RT_FALSE)
- continue;
- /* draw line */
- func(dst, draw_x1, draw_y1, draw_x2, draw_y2, blendMode, r, g, b, a, RT_TRUE);
- }
- }
- }
- else
- {
- if (dst->type == RTGUI_DC_HW)
- {
- rtgui_rect_t *prect;
- struct rtgui_dc_hw *dc_hw = (struct rtgui_dc_hw*)dst;
- owner = dc_hw->owner;
- x1 = x1 + owner->extent.x1;
- x2 = x2 + owner->extent.x1;
- y1 = y1 + owner->extent.y1;
- y2 = y2 + owner->extent.y1;
- prect = &(owner->clip.extents);
- if (_intersect_rect_line(prect, &x1, &y1, &x2, &y2) == RT_FALSE)
- return;
- }
- func(dst, x1, y1, x2, y2, blendMode, r, g, b, a, RT_TRUE);
- }
- }
- void
- rtgui_dc_blend_line(struct rtgui_dc * dst, int x1, int y1, int x2, int y2,
- enum RTGUI_BLENDMODE blendMode, rtgui_color_t color)
- {
- RT_ASSERT(dst != RT_NULL);
- if (!rtgui_dc_get_visible(dst))
- return;
- /* we do not support pixel DC */
- if (_dc_get_pixel(dst, 0, 0) == RT_NULL)
- return;
- _do_blend_line(dst, color, x1, y1, x2, y2, blendMode, RT_FALSE);
- }
- RTM_EXPORT(rtgui_dc_blend_line);
- void
- rtgui_dc_blend_lines(struct rtgui_dc * dst, const rtgui_point_t * points, int count,
- enum RTGUI_BLENDMODE blendMode, rtgui_color_t color)
- {
- int i;
- RT_ASSERT(dst != RT_NULL);
- if (!rtgui_dc_get_visible(dst))
- return;
- /* we do not support pixel DC */
- if (_dc_get_pixel(dst, 0, 0) == RT_NULL)
- return;
- for (i = 1; i < count; ++i)
- {
- rt_bool_t draw_end;
- int x1, y1, x2, y2;
- x1 = points[i-1].x;
- y1 = points[i-1].y;
- x2 = points[i].x;
- y2 = points[i].y;
- /* Draw the end if it was clipped */
- draw_end = (x2 != points[i].x || y2 != points[i].y);
- _do_blend_line(dst, color, x1, y1, x2, y2, blendMode, draw_end);
- }
- if (points[0].x != points[count-1].x || points[0].y != points[count-1].y)
- {
- rt_uint8_t r, g, b, a;
- r = RTGUI_RGB_R(color);
- g = RTGUI_RGB_G(color);
- b = RTGUI_RGB_B(color);
- a = RTGUI_RGB_A(color);
- rtgui_dc_blend_point(dst, points[count-1].x, points[count-1].y,
- blendMode, r, g, b, a);
- }
- }
- RTM_EXPORT(rtgui_dc_blend_lines);
- static void
- _dc_blend_fill_rect_rgb565(struct rtgui_dc * dst, const rtgui_rect_t * rect,
- enum RTGUI_BLENDMODE blendMode, rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
- {
- unsigned inva = 0xff - a;
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- FILLRECT(rt_uint16_t, DRAW_SETPIXEL_BLEND_RGB565);
- break;
- case RTGUI_BLENDMODE_ADD:
- FILLRECT(rt_uint16_t, DRAW_SETPIXEL_ADD_RGB565);
- break;
- case RTGUI_BLENDMODE_MOD:
- FILLRECT(rt_uint16_t, DRAW_SETPIXEL_MOD_RGB565);
- break;
- default:
- FILLRECT(rt_uint16_t, DRAW_SETPIXEL_RGB565);
- break;
- }
- }
- static void
- _dc_blend_fill_rect_bgr565(struct rtgui_dc * dst, const rtgui_rect_t * rect,
- enum RTGUI_BLENDMODE blendMode, rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
- {
- unsigned inva = 0xff - a;
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- FILLRECT(rt_uint16_t, DRAW_SETPIXEL_BLEND_RGB565);
- break;
- case RTGUI_BLENDMODE_ADD:
- FILLRECT(rt_uint16_t, DRAW_SETPIXEL_ADD_RGB565);
- break;
- case RTGUI_BLENDMODE_MOD:
- FILLRECT(rt_uint16_t, DRAW_SETPIXEL_MOD_RGB565);
- break;
- default:
- FILLRECT(rt_uint16_t, DRAW_SETPIXEL_RGB565);
- break;
- }
- }
- static void
- _dc_blend_fill_rect_rgb888(struct rtgui_dc * dst, const rtgui_rect_t * rect,
- enum RTGUI_BLENDMODE blendMode, rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
- {
- unsigned inva = 0xff - a;
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- FILLRECT(rt_uint32_t, DRAW_SETPIXEL_BLEND_RGB888);
- break;
- case RTGUI_BLENDMODE_ADD:
- FILLRECT(rt_uint32_t, DRAW_SETPIXEL_ADD_RGB888);
- break;
- case RTGUI_BLENDMODE_MOD:
- FILLRECT(rt_uint32_t, DRAW_SETPIXEL_MOD_RGB888);
- break;
- default:
- FILLRECT(rt_uint32_t, DRAW_SETPIXEL_RGB888);
- break;
- }
- }
- static void
- _dc_blend_fill_rect_argb8888(struct rtgui_dc * dst, const rtgui_rect_t * rect,
- enum RTGUI_BLENDMODE blendMode, rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a)
- {
- unsigned inva = 0xff - a;
- switch (blendMode)
- {
- case RTGUI_BLENDMODE_BLEND:
- FILLRECT(rt_uint32_t, DRAW_SETPIXEL_BLEND_ARGB8888);
- break;
- case RTGUI_BLENDMODE_ADD:
- FILLRECT(rt_uint32_t, DRAW_SETPIXEL_ADD_ARGB8888);
- break;
- case RTGUI_BLENDMODE_MOD:
- FILLRECT(rt_uint32_t, DRAW_SETPIXEL_MOD_ARGB8888);
- break;
- default:
- FILLRECT(rt_uint32_t, DRAW_SETPIXEL_ARGB8888);
- break;
- }
- }
- typedef void (*BlendFillFunc)(struct rtgui_dc * dst, const rtgui_rect_t * rect,
- enum RTGUI_BLENDMODE blendMode, rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a);
- void
- rtgui_dc_blend_fill_rect(struct rtgui_dc* dst, const rtgui_rect_t *rect,
- enum RTGUI_BLENDMODE blendMode, rtgui_color_t color)
- {
- unsigned r, g, b, a;
- BlendFillFunc func = RT_NULL;
- RT_ASSERT(dst != RT_NULL);
- if (!rtgui_dc_get_visible(dst)) return;
- /* This function doesn't work on surfaces < 8 bpp */
- if (_dc_get_bits_per_pixel(dst) < 8)
- {
- rt_kprintf("dc_blend_fill_rect(): Unsupported pixel format\n");
- return ;
- }
- r = RTGUI_RGB_R(color);
- g = RTGUI_RGB_G(color);
- b = RTGUI_RGB_B(color);
- a = RTGUI_RGB_A(color);
- if (blendMode == RTGUI_BLENDMODE_BLEND || blendMode == RTGUI_BLENDMODE_ADD)
- {
- r = DRAW_MUL(r, a);
- g = DRAW_MUL(g, a);
- b = DRAW_MUL(b, a);
- }
- switch (rtgui_dc_get_pixel_format(dst))
- {
- case RTGRAPHIC_PIXEL_FORMAT_RGB565:
- func = _dc_blend_fill_rect_rgb565;
- break;
- case RTGRAPHIC_PIXEL_FORMAT_BGR565:
- func = _dc_blend_fill_rect_bgr565;
- break;
- case RTGRAPHIC_PIXEL_FORMAT_RGB888:
- func = _dc_blend_fill_rect_rgb888;
- break;
- case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
- func = _dc_blend_fill_rect_argb8888;
- break;
- default:
- break;
- }
- if (func == RT_NULL)
- {
- rt_kprintf("dc_blend_fill_rect(): Unsupported pixel format\n");
- return ;
- }
- if (dst->type == RTGUI_DC_CLIENT)
- {
- register rt_base_t index;
- rtgui_widget_t *owner;
- rtgui_rect_t draw_rect;
- /* get owner */
- owner = RTGUI_CONTAINER_OF(dst, struct rtgui_widget, dc_type);
- if (owner->clip.data == RT_NULL)
- {
- rtgui_rect_t *prect;
- prect = &(owner->clip.extents);
- /* convert logic to device */
- draw_rect = *rect;
- rtgui_rect_move(&draw_rect,owner->extent.x1, owner->extent.y1);
- /* calculate rect intersect */
- if (prect->y1 > draw_rect.y2 || prect->y2 <= draw_rect.y1) return ;
- if (prect->x2 <= draw_rect.x1 || prect->x1 > draw_rect.x2 ) return ;
- rtgui_rect_intersect(prect, &draw_rect);
- func(dst, &draw_rect, blendMode, r, g, b, a);
- }
- else
- {
- for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++)
- {
- rtgui_rect_t *prect;
- prect = ((rtgui_rect_t *)(owner->clip.data + index + 1));
- draw_rect = *rect;
- rtgui_rect_move(&draw_rect,owner->extent.x1, owner->extent.y1);
- /* calculate rect intersect */
- if (prect->y1 > draw_rect.y2 || prect->y2 <= draw_rect.y1) continue;
- if (prect->x2 <= draw_rect.x1 || prect->x1 > draw_rect.x2 ) continue;
- rtgui_rect_intersect(prect, &draw_rect);
- func(dst, &draw_rect, blendMode, r, g, b, a);
- }
- }
- }
- else if (dst->type == RTGUI_DC_HW)
- {
- rtgui_rect_t draw_rect = *rect;
- struct rtgui_dc_hw *dc = (struct rtgui_dc_hw *) dst;
- draw_rect.x2 = dc->owner->extent.x1 + draw_rect.x2 - draw_rect.x1;
- draw_rect.y2 = dc->owner->extent.y1 + draw_rect.y2 - draw_rect.y1;
- draw_rect.x1 = dc->owner->extent.x1 > 0 ? dc->owner->extent.x1 : 0;
- draw_rect.y1 = dc->owner->extent.y1 > 0 ? dc->owner->extent.y1 : 0;
- draw_rect.x2 = draw_rect.x2 > hw_driver->width ? hw_driver->width : draw_rect.x2;
- draw_rect.y2 = draw_rect.y2 > hw_driver->height ? hw_driver->height : draw_rect.y2;
- func(dst, &draw_rect, blendMode, r, g, b, a);
- }
- else
- {
- func(dst, rect, blendMode, r, g, b, a);
- }
- }
- RTM_EXPORT(rtgui_dc_blend_fill_rect);
- void
- rtgui_dc_blend_fill_rects(struct rtgui_dc * dst, const rtgui_rect_t *rects, int count,
- enum RTGUI_BLENDMODE blendMode, rtgui_color_t color)
- {
- int i;
- rtgui_rect_t rect;
- BlendFillFunc func = RT_NULL;
- rt_uint8_t r, g, b, a;
- rtgui_widget_t *owner = RT_NULL;
- RT_ASSERT(dst != RT_NULL);
- if (!rtgui_dc_get_visible(dst)) return;
- /* This function doesn't work on surfaces < 8 bpp */
- if (_dc_get_bits_per_pixel(dst)< 8)
- {
- rt_kprintf("dc_blend_fill_rects(): Unsupported pixel format\n");
- return;
- }
- r = RTGUI_RGB_R(color);
- g = RTGUI_RGB_G(color);
- b = RTGUI_RGB_B(color);
- a = RTGUI_RGB_A(color);
- if (blendMode == RTGUI_BLENDMODE_BLEND || blendMode == RTGUI_BLENDMODE_ADD)
- {
- r = DRAW_MUL(r, a);
- g = DRAW_MUL(g, a);
- b = DRAW_MUL(b, a);
- }
- switch (rtgui_dc_get_pixel_format(dst))
- {
- case RTGRAPHIC_PIXEL_FORMAT_RGB565:
- func = _dc_blend_fill_rect_rgb565;
- break;
- case RTGRAPHIC_PIXEL_FORMAT_BGR565:
- func = _dc_blend_fill_rect_bgr565;
- break;
- case RTGRAPHIC_PIXEL_FORMAT_RGB888:
- func = _dc_blend_fill_rect_rgb888;
- break;
- case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
- func = _dc_blend_fill_rect_argb8888;
- break;
- default:
- break;
- }
- if (func == RT_NULL)
- {
- rt_kprintf("dc_blend_fill_rects(): Unsupported pixel format\n");
- return;
- }
- if (dst->type == RTGUI_DC_CLIENT)
- {
- /* get owner */
- owner = RTGUI_CONTAINER_OF(dst, struct rtgui_widget, dc_type);
- }
- for (i = 0; i < count; ++i)
- {
- rect = rects[i];
- if (dst->type == RTGUI_DC_CLIENT)
- {
- register rt_base_t index;
- rtgui_rect_t draw_rect;
- if (owner->clip.data == RT_NULL)
- {
- rtgui_rect_t *prect;
- prect = &(owner->clip.extents);
- /* convert logic to device */
- draw_rect = rect;
- rtgui_rect_move(&draw_rect,owner->extent.x1, owner->extent.y1);
- /* calculate rect intersect */
- if (prect->y1 > draw_rect.y2 || prect->y2 <= draw_rect.y1) return ;
- if (prect->x2 <= draw_rect.x1 || prect->x1 > draw_rect.x2 ) return ;
- rtgui_rect_intersect(prect, &draw_rect);
- func(dst, &draw_rect, blendMode, r, g, b, a);
- }
- else
- {
- for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++)
- {
- rtgui_rect_t *prect;
- prect = ((rtgui_rect_t *)(owner->clip.data + index + 1));
- draw_rect = rect;
- rtgui_rect_move(&draw_rect,owner->extent.x1, owner->extent.y1);
- /* calculate rect intersect */
- if (prect->y1 > draw_rect.y2 || prect->y2 <= draw_rect.y1) continue;
- if (prect->x2 <= draw_rect.x1 || prect->x1 > draw_rect.x2 ) continue;
- rtgui_rect_intersect(prect, &draw_rect);
- func(dst, &draw_rect, blendMode, r, g, b, a);
- }
- }
- }
- else
- {
- func(dst, &rect, blendMode, r, g, b, a);
- }
- }
- }
- RTM_EXPORT(rtgui_dc_blend_fill_rects);
- /* Windows targets do not have lrint, so provide a local inline version */
- #if defined(_MSC_VER)
- /* Detect 64bit and use intrinsic version */
- #ifdef _M_X64
- #include <emmintrin.h>
- static __inline long
- lrint(float f)
- {
- return _mm_cvtss_si32(_mm_load_ss(&f));
- }
- #elif defined(_M_IX86)
- __inline long int
- lrint (double flt)
- {
- int intgr;
- _asm
- {
- fld flt
- fistp intgr
- };
- return intgr;
- }
- #elif defined(_M_ARM)
- #include <armintr.h>
- #pragma warning(push)
- #pragma warning(disable: 4716)
- __declspec(naked) long int
- lrint (double flt)
- {
- __emit(0xEC410B10); // fmdrr d0, r0, r1
- __emit(0xEEBD0B40); // ftosid s0, d0
- __emit(0xEE100A10); // fmrs r0, s0
- __emit(0xE12FFF1E); // bx lr
- }
- #pragma warning(pop)
- #else
- #error lrint needed for MSVC on non X86/AMD64/ARM targets.
- #endif
- #endif
- rt_inline void _draw_pixel_weight(struct rtgui_dc * dc, rt_int16_t x, rt_int16_t y,
- rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, rt_uint8_t a, rt_uint32_t weight)
- {
- /*
- * Modify Alpha by weight
- */
- rt_uint32_t ax = a;
- ax = ((ax * weight) >> 8);
- if (ax > 255)
- {
- a = 255;
- }
- else
- {
- a = (rt_uint8_t)(ax & 0x000000ff);
- }
- rtgui_dc_blend_point(dc, x, y, RTGUI_BLENDMODE_BLEND, r, g, b, a);
- }
- 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)
- {
- int i;
- int a2, b2, ds, dt, dxt, t, s, d;
- rt_int16_t xp, yp, xs, ys, od, dyt, xx, yy, xc2, yc2;
- int cp;
- double sab;
- rt_uint8_t weight, iweight;
- rt_uint8_t r, g, b, a;
- /* Sanity check radii */
- if ((rx < 0) || (ry < 0)) return ;
- /*
- * Special case for rx=0 - draw a vline
- */
- if (rx == 0)
- {
- rtgui_dc_draw_vline(dc, x, y - ry, y + ry);
- return;
- }
- /*
- * Special case for ry=0 - draw an hline
- */
- if (ry == 0)
- {
- rtgui_dc_draw_hline(dc, x - rx, x + rx, y);
- return;
- }
- /* Variable setup */
- r = RTGUI_RGB_R(RTGUI_DC_FC(dc));
- g = RTGUI_RGB_G(RTGUI_DC_FC(dc));
- b = RTGUI_RGB_B(RTGUI_DC_FC(dc));
- a = RTGUI_RGB_A(RTGUI_DC_FC(dc));
- a2 = rx * rx;
- b2 = ry * ry;
- ds = 2 * a2;
- dt = 2 * b2;
- xc2 = 2 * x;
- yc2 = 2 * y;
- sab = sqrt((double)(a2 + b2));
- od = (rt_int16_t)lrint(sab*0.01) + 1; /* introduce some overdraw */
- dxt = (rt_int16_t)lrint((double)a2 / sab) + od;
- t = 0;
- s = -2 * a2 * ry;
- d = 0;
- xp = x;
- yp = y - ry;
- /* Draw */
- /* "End points" */
- rtgui_dc_blend_point(dc, xp, yp, RTGUI_BLENDMODE_NONE, r, g, b, a);
- rtgui_dc_blend_point(dc, xc2 - xp, yp, RTGUI_BLENDMODE_NONE, r, g, b, a);
- rtgui_dc_blend_point(dc, xp, yc2 - yp, RTGUI_BLENDMODE_NONE, r, g, b, a);
- rtgui_dc_blend_point(dc, xc2 - xp, yc2 - yp, RTGUI_BLENDMODE_NONE, r, g, b, a);
- for (i = 1; i <= dxt; i++)
- {
- xp--;
- d += t - b2;
- if (d >= 0)
- ys = yp - 1;
- else if ((d - s - a2) > 0)
- {
- if ((2 * d - s - a2) >= 0)
- ys = yp + 1;
- else
- {
- ys = yp;
- yp++;
- d -= s + a2;
- s += ds;
- }
- }
- else
- {
- yp++;
- ys = yp + 1;
- d -= s + a2;
- s += ds;
- }
- t -= dt;
- /* Calculate alpha */
- if (s != 0)
- {
- cp = 255 * abs(d) / abs(s);
- if (cp > 255)
- {
- cp = 255;
- }
- }
- else
- {
- cp = 255;
- }
- /* Calculate weights */
- weight = cp;
- iweight = 255 - weight;
- /* Upper half */
- xx = xc2 - xp;
- _draw_pixel_weight(dc, xp, yp, r, g, b, a, iweight);
- _draw_pixel_weight(dc, xx, yp, r, g, b, a, iweight);
- _draw_pixel_weight(dc, xp, ys, r, g, b, a, weight);
- _draw_pixel_weight(dc, xx, ys, r, g, b, a, weight);
- /* Lower half */
- yy = yc2 - yp;
- _draw_pixel_weight(dc, xp, yy, r, g, b, a, iweight);
- _draw_pixel_weight(dc, xx, yy, r, g, b, a, iweight);
- yy = yc2 - ys;
- _draw_pixel_weight(dc, xp, yy, r, g, b, a, weight);
- _draw_pixel_weight(dc, xx, yy, r, g, b, a, weight);
- }
- /* Replaces original approximation code dyt = abs(yp - yc); */
- dyt = (rt_int16_t)lrint((double)b2 / sab ) + od;
- for (i = 1; i <= dyt; i++)
- {
- yp++;
- d -= s + a2;
- if (d <= 0)
- xs = xp + 1;
- else if ((d + t - b2) < 0)
- {
- if ((2 * d + t - b2) <= 0)
- xs = xp - 1;
- else
- {
- xs = xp;
- xp--;
- d += t - b2;
- t -= dt;
- }
- }
- else
- {
- xp--;
- xs = xp - 1;
- d += t - b2;
- t -= dt;
- }
- s += ds;
- /* Calculate alpha */
- if (t != 0)
- {
- cp = 255 * abs(d) / abs(t);
- if (cp > 255)
- {
- cp = 255;
- }
- }
- else
- {
- cp = 255;
- }
- /* Calculate weight */
- weight = cp;
- iweight = 255 - weight;
- /* Left half */
- xx = xc2 - xp;
- yy = yc2 - yp;
- _draw_pixel_weight(dc, xp, yp, r, g, b, a, iweight);
- _draw_pixel_weight(dc, xx, yp, r, g, b, a, iweight);
- _draw_pixel_weight(dc, xp, yy, r, g, b, a, iweight);
- _draw_pixel_weight(dc, xx, yy, r, g, b, a, iweight);
- /* Right half */
- xx = xc2 - xs;
- _draw_pixel_weight(dc, xs, yp, r, g, b, a, weight);
- _draw_pixel_weight(dc, xx, yp, r, g, b, a, weight);
- _draw_pixel_weight(dc, xs, yy, r, g, b, a, weight);
- _draw_pixel_weight(dc, xx, yy, r, g, b, a, weight);
- }
- }
- RTM_EXPORT(rtgui_dc_draw_aa_ellipse);
- void rtgui_dc_draw_aa_circle(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t r)
- {
- rtgui_dc_draw_aa_ellipse(dc, x, y, r, r);
- }
- RTM_EXPORT(rtgui_dc_draw_aa_circle);
- /*!
- \brief The structure passed to the internal Bresenham iterator.
- */
- typedef struct
- {
- rt_int16_t x, y;
- int dx, dy, s1, s2, swapdir, error;
- rt_uint32_t count;
- } _BresenhamIterator;
- /*!
- \brief The structure passed to the internal Murphy iterator.
- */
- typedef struct
- {
- rt_uint32_t color;
- struct rtgui_dc *dst;
- int u, v; /* delta x , delta y */
- int ku, kt, kv, kd; /* loop constants */
- int oct2;
- int quad4;
- rt_int16_t last1x, last1y, last2x, last2y, first1x, first1y, first2x, first2y, tempx, tempy;
- } _MurphyIterator;
- /*!
- \brief Internal function to initialize the Bresenham line iterator.
- Example of use:
- _BresenhamIterator b;
- _bresenhamInitialize (&b, x1, y1, x2, y2);
- do {
- plot(b.x, b.y);
- } while (_bresenhamIterate(&b)==0);
- \param b Pointer to struct for bresenham line drawing state.
- \param x1 X coordinate of the first point of the line.
- \param y1 Y coordinate of the first point of the line.
- \param x2 X coordinate of the second point of the line.
- \param y2 Y coordinate of the second point of the line.
- \returns Returns 0 on success, -1 on failure.
- */
- int _bresenhamInitialize(_BresenhamIterator *b, rt_int16_t x1, rt_int16_t y1, rt_int16_t x2, rt_int16_t y2)
- {
- int temp;
- if (b==NULL)
- {
- return(-1);
- }
- b->x = x1;
- b->y = y1;
- /* dx = abs(x2-x1), s1 = sign(x2-x1) */
- if ((b->dx = x2 - x1) != 0)
- {
- if (b->dx < 0)
- {
- b->dx = -b->dx;
- b->s1 = -1;
- }
- else
- {
- b->s1 = 1;
- }
- }
- else
- {
- b->s1 = 0;
- }
- /* dy = abs(y2-y1), s2 = sign(y2-y1) */
- if ((b->dy = y2 - y1) != 0)
- {
- if (b->dy < 0)
- {
- b->dy = -b->dy;
- b->s2 = -1;
- }
- else
- {
- b->s2 = 1;
- }
- }
- else
- {
- b->s2 = 0;
- }
- if (b->dy > b->dx)
- {
- temp = b->dx;
- b->dx = b->dy;
- b->dy = temp;
- b->swapdir = 1;
- }
- else
- {
- b->swapdir = 0;
- }
- b->count = (b->dx<0) ? 0 : (unsigned int)b->dx;
- b->dy <<= 1;
- b->error = b->dy - b->dx;
- b->dx <<= 1;
- return(0);
- }
- /*!
- \brief Internal function to move Bresenham line iterator to the next position.
- Maybe updates the x and y coordinates of the iterator struct.
- \param b Pointer to struct for bresenham line drawing state.
- \returns Returns 0 on success, 1 if last point was reached, 2 if moving past end-of-line, -1 on failure.
- */
- int _bresenhamIterate(_BresenhamIterator *b)
- {
- if (b==NULL)
- {
- return (-1);
- }
- /* last point check */
- if (b->count==0)
- {
- return (2);
- }
- while (b->error >= 0)
- {
- if (b->swapdir)
- {
- b->x += b->s1;
- }
- else
- {
- b->y += b->s2;
- }
- b->error -= b->dx;
- }
- if (b->swapdir)
- {
- b->y += b->s2;
- }
- else
- {
- b->x += b->s1;
- }
- b->error += b->dy;
- b->count--;
- /* count==0 indicates "end-of-line" */
- return ((b->count) ? 0 : 1);
- }
- /*!
- \brief Internal function to to draw parallel lines with Murphy algorithm.
- \param m Pointer to struct for murphy iterator.
- \param x X coordinate of point.
- \param y Y coordinate of point.
- \param d1 Direction square/diagonal.
- */
- void _murphyParaline(_MurphyIterator *m, rt_int16_t x, rt_int16_t y, int d1)
- {
- int p;
- d1 = -d1;
- for (p = 0; p <= m->u; p++)
- {
- rtgui_dc_draw_point(m->dst, x, y);
- if (d1 <= m->kt)
- {
- if (m->oct2 == 0)
- {
- x++;
- }
- else
- {
- if (m->quad4 == 0)
- {
- y++;
- }
- else
- {
- y--;
- }
- }
- d1 += m->kv;
- }
- else
- {
- x++;
- if (m->quad4 == 0)
- {
- y++;
- }
- else
- {
- y--;
- }
- d1 += m->kd;
- }
- }
- m->tempx = x;
- m->tempy = y;
- }
- /*!
- \brief Internal function to to draw one iteration of the Murphy algorithm.
- \param m Pointer to struct for murphy iterator.
- \param miter Iteration count.
- \param ml1bx X coordinate of a point.
- \param ml1by Y coordinate of a point.
- \param ml2bx X coordinate of a point.
- \param ml2by Y coordinate of a point.
- \param ml1x X coordinate of a point.
- \param ml1y Y coordinate of a point.
- \param ml2x X coordinate of a point.
- \param ml2y Y coordinate of a point.
- */
- void _murphyIteration(_MurphyIterator *m, rt_uint8_t miter,
- rt_uint16_t ml1bx, rt_uint16_t ml1by, rt_uint16_t ml2bx, rt_uint16_t ml2by,
- rt_uint16_t ml1x, rt_uint16_t ml1y, rt_uint16_t ml2x, rt_uint16_t ml2y)
- {
- int atemp1, atemp2;
- int ftmp1, ftmp2;
- rt_uint16_t m1x, m1y, m2x, m2y;
- rt_uint16_t fix, fiy, lax, lay, curx, cury;
- int px[4], py[4];
- _BresenhamIterator b;
- if (miter > 1)
- {
- if (m->first1x != -32768)
- {
- fix = (m->first1x + m->first2x) / 2;
- fiy = (m->first1y + m->first2y) / 2;
- lax = (m->last1x + m->last2x) / 2;
- lay = (m->last1y + m->last2y) / 2;
- curx = (ml1x + ml2x) / 2;
- cury = (ml1y + ml2y) / 2;
- atemp1 = (fix - curx);
- atemp2 = (fiy - cury);
- ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
- atemp1 = (lax - curx);
- atemp2 = (lay - cury);
- ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
- if (ftmp1 <= ftmp2)
- {
- m1x = m->first1x;
- m1y = m->first1y;
- m2x = m->first2x;
- m2y = m->first2y;
- }
- else
- {
- m1x = m->last1x;
- m1y = m->last1y;
- m2x = m->last2x;
- m2y = m->last2y;
- }
- atemp1 = (m2x - ml2x);
- atemp2 = (m2y - ml2y);
- ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
- atemp1 = (m2x - ml2bx);
- atemp2 = (m2y - ml2by);
- ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
- if (ftmp2 >= ftmp1)
- {
- ftmp1 = ml2bx;
- ftmp2 = ml2by;
- ml2bx = ml2x;
- ml2by = ml2y;
- ml2x = ftmp1;
- ml2y = ftmp2;
- ftmp1 = ml1bx;
- ftmp2 = ml1by;
- ml1bx = ml1x;
- ml1by = ml1y;
- ml1x = ftmp1;
- ml1y = ftmp2;
- }
- _bresenhamInitialize(&b, m2x, m2y, m1x, m1y);
- do
- {
- rtgui_dc_draw_color_point(m->dst, b.x, b.y, m->color);
- }
- while (_bresenhamIterate(&b)==0);
- _bresenhamInitialize(&b, m1x, m1y, ml1bx, ml1by);
- do
- {
- rtgui_dc_draw_color_point(m->dst, b.x, b.y, m->color);
- }
- while (_bresenhamIterate(&b)==0);
- _bresenhamInitialize(&b, ml1bx, ml1by, ml2bx, ml2by);
- do
- {
- rtgui_dc_draw_color_point(m->dst, b.x, b.y, m->color);
- }
- while (_bresenhamIterate(&b)==0);
- _bresenhamInitialize(&b, ml2bx, ml2by, m2x, m2y);
- do
- {
- rtgui_dc_draw_color_point(m->dst, b.x, b.y, m->color);
- }
- while (_bresenhamIterate(&b)==0);
- px[0] = m1x;
- px[1] = m2x;
- px[2] = ml1bx;
- px[3] = ml2bx;
- py[0] = m1y;
- py[1] = m2y;
- py[2] = ml1by;
- py[3] = ml2by;
- rtgui_dc_draw_polygon(m->dst, px, py, 4);
- }
- }
- m->last1x = ml1x;
- m->last1y = ml1y;
- m->last2x = ml2x;
- m->last2y = ml2y;
- m->first1x = ml1bx;
- m->first1y = ml1by;
- m->first2x = ml2bx;
- m->first2y = ml2by;
- }
- #define HYPOT(x,y) sqrt((double)(x)*(double)(x)+(double)(y)*(double)(y))
- /*!
- \brief Internal function to to draw wide lines with Murphy algorithm.
- Draws lines parallel to ideal line.
- \param m Pointer to struct for murphy iterator.
- \param x1 X coordinate of first point.
- \param y1 Y coordinate of first point.
- \param x2 X coordinate of second point.
- \param y2 Y coordinate of second point.
- \param width Width of line.
- \param miter Iteration count.
- */
- 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)
- {
- float offset = (float)width / 2.f;
- rt_int16_t temp;
- rt_int16_t ptx, pty, ml1x, ml1y, ml2x, ml2y, ml1bx, ml1by, ml2bx, ml2by;
- int d0, d1; /* difference terms d0=perpendicular to line, d1=along line */
- int q; /* pel counter,q=perpendicular to line */
- int tmp;
- int dd; /* distance along line */
- int tk; /* thickness threshold */
- double ang; /* angle for initial point calculation */
- double sang, cang;
- /* Initialisation */
- m->u = x2 - x1; /* delta x */
- m->v = y2 - y1; /* delta y */
- if (m->u < 0) /* swap to make sure we are in quadrants 1 or 4 */
- {
- temp = x1;
- x1 = x2;
- x2 = temp;
- temp = y1;
- y1 = y2;
- y2 = temp;
- m->u *= -1;
- m->v *= -1;
- }
- if (m->v < 0) /* swap to 1st quadrant and flag */
- {
- m->v *= -1;
- m->quad4 = 1;
- }
- else
- {
- m->quad4 = 0;
- }
- if (m->v > m->u) /* swap things if in 2 octant */
- {
- tmp = m->u;
- m->u = m->v;
- m->v = tmp;
- m->oct2 = 1;
- }
- else
- {
- m->oct2 = 0;
- }
- m->ku = m->u + m->u; /* change in l for square shift */
- m->kv = m->v + m->v; /* change in d for square shift */
- m->kd = m->kv - m->ku; /* change in d for diagonal shift */
- m->kt = m->u - m->kv; /* diag/square decision threshold */
- d0 = 0;
- d1 = 0;
- dd = 0;
- ang = atan((double) m->v / (double) m->u); /* calc new initial point - offset both sides of ideal */
- sang = sin(ang);
- cang = cos(ang);
- if (m->oct2 == 0)
- {
- ptx = x1 + (rt_int16_t)lrint(offset * sang);
- if (m->quad4 == 0)
- {
- pty = y1 - (rt_int16_t)lrint(offset * cang);
- }
- else
- {
- pty = y1 + (rt_int16_t)lrint(offset * cang);
- }
- }
- else
- {
- ptx = x1 - (rt_int16_t)lrint(offset * cang);
- if (m->quad4 == 0)
- {
- pty = y1 + (rt_int16_t)lrint(offset * sang);
- }
- else
- {
- pty = y1 - (rt_int16_t)lrint(offset * sang);
- }
- }
- /* used here for constant thickness line */
- tk = (int) (4. * HYPOT(ptx - x1, pty - y1) * HYPOT(m->u, m->v));
- if (miter == 0)
- {
- m->first1x = -32768;
- m->first1y = -32768;
- m->first2x = -32768;
- m->first2y = -32768;
- m->last1x = -32768;
- m->last1y = -32768;
- m->last2x = -32768;
- m->last2y = -32768;
- }
- for (q = 0; dd <= tk; q++) /* outer loop, stepping perpendicular to line */
- {
- _murphyParaline(m, ptx, pty, d1); /* call to inner loop - right edge */
- if (q == 0)
- {
- ml1x = ptx;
- ml1y = pty;
- ml1bx = m->tempx;
- ml1by = m->tempy;
- }
- else
- {
- ml2x = ptx;
- ml2y = pty;
- ml2bx = m->tempx;
- ml2by = m->tempy;
- }
- if (d0 < m->kt) /* square move */
- {
- if (m->oct2 == 0)
- {
- if (m->quad4 == 0)
- {
- pty++;
- }
- else
- {
- pty--;
- }
- }
- else
- {
- ptx++;
- }
- }
- else /* diagonal move */
- {
- dd += m->kv;
- d0 -= m->ku;
- if (d1 < m->kt) /* normal diagonal */
- {
- if (m->oct2 == 0)
- {
- ptx--;
- if (m->quad4 == 0)
- {
- pty++;
- }
- else
- {
- pty--;
- }
- }
- else
- {
- ptx++;
- if (m->quad4 == 0)
- {
- pty--;
- }
- else
- {
- pty++;
- }
- }
- d1 += m->kv;
- }
- else /* double square move, extra parallel line */
- {
- if (m->oct2 == 0)
- {
- ptx--;
- }
- else
- {
- if (m->quad4 == 0)
- {
- pty--;
- }
- else
- {
- pty++;
- }
- }
- d1 += m->kd;
- if (dd > tk)
- {
- _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
- return; /* breakout on the extra line */
- }
- _murphyParaline(m, ptx, pty, d1);
- if (m->oct2 == 0)
- {
- if (m->quad4 == 0)
- {
- pty++;
- }
- else
- {
- pty--;
- }
- }
- else
- {
- ptx++;
- }
- }
- }
- dd += m->ku;
- d0 += m->kv;
- }
- _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
- }
- /*!
- \brief Draw a thick line with alpha blending.
- \param dst The surface to draw on.
- \param x1 X coordinate of the first point of the line.
- \param y1 Y coordinate of the first point of the line.
- \param x2 X coordinate of the second point of the line.
- \param y2 Y coordinate of the second point of the line.
- \param width Width of the line in pixels. Must be >0.
- \param color The color value of the line to draw (0xRRGGBBAA).
- \returns Returns 0 on success, -1 on failure.
- */
- 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)
- {
- int wh;
- _MurphyIterator m;
- if (dst == NULL) return -1;
- if (width < 1) return -1;
- /* Special case: thick "point" */
- if ((x1 == x2) && (y1 == y2))
- {
- struct rtgui_rect rect;
- wh = width / 2;
- rtgui_rect_init(&rect, x1 - wh, y1 - wh, x2 + width, y2 + width);
- rtgui_dc_fill_rect(dst, &rect);
- }
- m.dst = dst;
- m.color = RTGUI_DC_FC(dst);
- _murphyWideline(&m, x1, y1, x2, y2, width, 0);
- _murphyWideline(&m, x1, y1, x2, y2, width, 1);
- return(0);
- }
- RTM_EXPORT(rtgui_dc_draw_thick_line);
|