diff --git a/inc/thorvg.h b/inc/thorvg.h index 84bbb308..4d4c18bd 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -279,6 +279,7 @@ public: Result load(const std::string& path) noexcept; Result load(const char* data, uint32_t size) noexcept; + Result load(uint32_t* data, uint32_t w, uint32_t h, bool copy) noexcept; Result viewbox(float* x, float* y, float* w, float* h) const noexcept; static std::unique_ptr gen() noexcept; diff --git a/meson.build b/meson.build index 3673c53d..9193a524 100644 --- a/meson.build +++ b/meson.build @@ -6,7 +6,7 @@ project('thorvg', config_h = configuration_data() -add_project_arguments('-DEXAMPLE_DIR="@0@/src/examples/svgs"'.format(meson.current_source_dir()), language : 'cpp') +add_project_arguments('-DEXAMPLE_DIR="@0@/src/examples/images"'.format(meson.current_source_dir()), language : 'cpp') if get_option('engines').contains('sw') == true config_h.set10('THORVG_SW_RASTER_SUPPORT', true) diff --git a/src/examples/PixelImage.cpp b/src/examples/PixelImage.cpp new file mode 100644 index 00000000..61d13000 --- /dev/null +++ b/src/examples/PixelImage.cpp @@ -0,0 +1,157 @@ +#include "Common.h" +#include + +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ + +uint32_t *data = nullptr; + +void tvgDrawCmds(tvg::Canvas* canvas) +{ + if (!canvas) return; + + //Background + auto shape = tvg::Shape::gen(); + shape->appendRect(0, 0, WIDTH, HEIGHT, 0, 0); + shape->fill(255, 255, 255, 255); + + if (canvas->push(move(shape)) != tvg::Result::Success) return; + + string path(EXAMPLE_DIR"/rawimage_200x300.raw"); + + ifstream file(path); + if (!file.is_open()) return ; + data = (uint32_t*)malloc(sizeof(uint32_t) * (200*300)); + file.read(reinterpret_cast(data), sizeof (data) * 200 * 300); + file.close(); + + auto picture = tvg::Picture::gen(); + if (picture->load(data, 200, 300, true) != tvg::Result::Success) return; + picture->translate(400, 250); + canvas->push(move(picture)); + + auto picture2 = tvg::Picture::gen(); + if (picture2->load(data, 200, 300, true) != tvg::Result::Success) return; + + picture2->translate(400, 200); + picture2->rotate(47); + picture2->scale(1.5); + picture2->opacity(128); + + auto circle = tvg::Shape::gen(); + circle->appendCircle(350, 350, 200,200); + circle->fill(255, 255, 255, 255); + + picture2->composite(move(circle), tvg::CompositeMethod::ClipPath); + + canvas->push(move(picture2)); +} + + +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ + +static unique_ptr swCanvas; + +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); +} + +void drawSwView(void* data, Eo* obj) +{ + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } +} + + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); +} + +void drawGLview(Evas_Object *obj) +{ + auto gl = elm_glview_gl_api_get(obj); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } +} + + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + +int main(int argc, char **argv) +{ + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; + + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } + + //Initialize ThorVG Engine + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } + + //Threads Count + auto threads = std::thread::hardware_concurrency(); + + //Initialize ThorVG Engine + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { + + elm_init(argc, argv); + + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } + + elm_run(); + elm_shutdown(); + + //Terminate ThorVG Engine + tvg::Initializer::term(tvg::CanvasEngine::Sw); + + if (data) free(data); + + } else { + cout << "engine is not supported" << endl; + } + return 0; +} diff --git a/src/examples/svgs/bojo.svg b/src/examples/images/bojo.svg similarity index 100% rename from src/examples/svgs/bojo.svg rename to src/examples/images/bojo.svg diff --git a/src/examples/svgs/bzrfeed.svg b/src/examples/images/bzrfeed.svg similarity index 100% rename from src/examples/svgs/bzrfeed.svg rename to src/examples/images/bzrfeed.svg diff --git a/src/examples/svgs/cartman.svg b/src/examples/images/cartman.svg similarity index 100% rename from src/examples/svgs/cartman.svg rename to src/examples/images/cartman.svg diff --git a/src/examples/svgs/dst.svg b/src/examples/images/dst.svg similarity index 100% rename from src/examples/svgs/dst.svg rename to src/examples/images/dst.svg diff --git a/src/examples/svgs/duke.svg b/src/examples/images/duke.svg similarity index 100% rename from src/examples/svgs/duke.svg rename to src/examples/images/duke.svg diff --git a/src/examples/svgs/eee.svg b/src/examples/images/eee.svg similarity index 100% rename from src/examples/svgs/eee.svg rename to src/examples/images/eee.svg diff --git a/src/examples/svgs/favorite_on.svg b/src/examples/images/favorite_on.svg similarity index 100% rename from src/examples/svgs/favorite_on.svg rename to src/examples/images/favorite_on.svg diff --git a/src/examples/svgs/google.svg b/src/examples/images/google.svg similarity index 100% rename from src/examples/svgs/google.svg rename to src/examples/images/google.svg diff --git a/src/examples/svgs/ibm.svg b/src/examples/images/ibm.svg similarity index 100% rename from src/examples/svgs/ibm.svg rename to src/examples/images/ibm.svg diff --git a/src/examples/svgs/lineargrad1.svg b/src/examples/images/lineargrad1.svg similarity index 100% rename from src/examples/svgs/lineargrad1.svg rename to src/examples/images/lineargrad1.svg diff --git a/src/examples/svgs/logo.svg b/src/examples/images/logo.svg similarity index 100% rename from src/examples/svgs/logo.svg rename to src/examples/images/logo.svg diff --git a/src/examples/svgs/radialgrad1.svg b/src/examples/images/radialgrad1.svg similarity index 100% rename from src/examples/svgs/radialgrad1.svg rename to src/examples/images/radialgrad1.svg diff --git a/src/examples/images/rawimage_200x300.raw b/src/examples/images/rawimage_200x300.raw new file mode 100644 index 00000000..83958db7 --- /dev/null +++ b/src/examples/images/rawimage_200x300.raw @@ -0,0 +1,110 @@ +kkl~l}l{kylxjtjrjsjtjzj|j|k}k}k{jzj{iyhugsfpfpenemfoepeqergthuiviwiwjzi|i{k}k}k~klkk~k~klk~k|kzjxkwisiqioipiqisiririqiphphnhkgghfhehehdhcibicjbjbi`j`i_h]h]i]h\h]h\gZhYh[h\h[gYgYfXgWfWfVeTeTfUeTeUeTeTeSdSeTfXiZhZi\h]h^g_hah_e^d]c]c]b\a\a\b`bcepetdueweze|e{dwcsapaoaoanamap`n_l^i^h^m`q`s_sa{b`{_t^r^r^u_u]s\r\p[kZjZjYgXbW`XcYiZkYkXjXjYp\{]~\}[y[vYoWgWgWgXiYkXjXiXjWjWjViWlXpWqXrWsYvXuVnVkVlUjSdkkl}l{lzmykvktktlrjukzl~ml|kwkwkxkyjvhtirirhrgpfofpepergrhuhviwiyiyj{j|j|j}k~lllmlllmm~l|kzlylykvjrjpjpjqjriqjsjrjsjsiqipikhjihificibjbjcjcjcibk`j`j`j^i^i]i[h[iYiYiYh[hZhZh[hZgXhXgXgWhXgWfVfVfVfUfUeVfWgXh\j]j^g_f_fahdidhbfbc_c_b`b`b`a`cffqgvgyg|ghgf}dzcubr`l_h_g_h_i`j_j^f^g^las_taza}`x^q^o^n^r^s]r\o\m[jZjZhYdYcYcXcYeYeXgYgYiYl\v\|\{\z\wZrYlXjXjYmYnYlXlXoYoXmWmXoXqXsXsXuYuXrVlUfUeUeTckkmmnnmzmwlvkulwn}onlzktktlvlxjujtirjtktishshqfrgqgrhuiwiyk|j}j|j~j~k~kllmlmlmlmm~l{lxlylwltkqlpkqkpkqjqjrksktkuktkqjmjlihjfjeieidiekeiajcjbjbjbi_i\j]j\j[iYiYj[i[j\i[h[hXhXiYhZhYhYgWgVfUfVfVfXgYg\i^jai`icicifihhdhdgfgeeceddedededheqgxg}hhhgf~f}eycs`j`i_h_h`j`l`l^f]c^g`n`q`s`s_n\j[i\h]k]o]n\k[hZhYfZdXbXaW`X^W_XaXdXeYhZj[q]y[x\x\w[s[pZlZnZqZqYoZrZsZrZqYqZsZtXsYsXsXrXoVgT`T`T_S^mlmmnnm|nzmzmym{o~onlykslsluluktktltjskvkuisirhrhqhsiuiwi{k}j~kk~kkklmmmmmlmmmm{mzmxlvlulsmqlolololpkpkrktlvkujtkskpjljkkijgifiekejdjdkejdjblbkak^k\j[jYjZj[j[j]i\iZiXiXiZjZiZiXgUgWgVgWgXhYh\h]h_iagckfkglgiffbgcfdfdeeefefegfjemgth{h}ggghf~e}dzcrajaiaj`i`j`n`k_h^e]f^i_m`p_l^h]g\e\e\h]j]kZeYbXaXaYaX`X`W]W\W]W_XaXdYfYj[r[t\v\w\w[r[m[k[p[rZqZp[v[wZtZsZtZtZsXrXpWoWoVkVdT^S\S[SZpomlmmmm|m|n}o~pon~mxltltmsmsmrlrlslskukvksiriqiririujxj{k}llmmmnmmnnmmmnnno~o|nynwnvmtlqnpmomolplplpltlumvlvkulrkpknklkkkjlilhkfkgkfkfjeldlbl`l_l]k[k[k\k]k^k]j[jYjYiZj[k[hXgWiVhVhXhYi[i]i^h`g`idjgkhlhkggcgdgegdggfhghfjelfofthyh|ihgg~ggezesakai`h`i_h_i_j_i^g^g`l`n_n_j]f\e\e\f\g\i\i[fYcYaZbYcYaXaX`X_XaXaXaYdXfZk[p\r[t]x\v[pZjZj\q\sZqZq[v[vZrZsZtZsYrYqXqYqXmWiVdT_R[SZRYpoonmnmooopppo|nwmvmrnrnqnqnqmsmtnumvmvksjqiqjsitjwkxkzl~mnnnnnnnonmnoonoo~ozoxoxnvmsnroqnpmonomonqmsmsmumumtmrlplplnlmlmkkljljkgkhlglfldmclal^l]l]l\l]l]l]k\k[jZkZj[j\jZhWiVhVhXiZi\i]i^i_i`hcidlhmikhjgkhkjkjikhigiglgogpgshxi}h~hh~g~f}f~f|eubnah`f`h_f_g_j^i^g^h`m_n`n^j\c\b]f]h\i\j]k\i\g[f[h[gZfZeZfYfZfZfXdXcXeZiZk\o\s\v]u[pZkZm\r\u[s[r\t[sZqZrZtYsZuZtZuYsXnWhVeT`S]SZRXpqqpoonnopqqqp{ozoxotosornpnqorosotnwowlslqjpksjtjukwlyl}nnnnonnopooooooooo}ozpzozovouornooooonnnononpnqnrmrmrmpmomomnmmmnllljljljlhlglfmemdmcm`l^m_l]l]l]l\l\k[k[k[k[jZjXjWjWjYj[jZj\j^i_i`jbjbjckgkgjfmimklkjlgifhhngpgqhrhuhzj}ih|f{g{g|f{etclah`e`e_f_i_i_h_g_g_i_k`m^h]d\`[c]k\k]k[l]l\g\i]n\m\m\k[l[m[kYgYfXdYeYfYiZl\o]w]v\r\o\o\r]u]u[r[r[r[p[rZs[t[vYrZqYpXlVgVeU`T\RZSYqqrrqqpppprrrqq}pyqwpsqsqrpqpqqsptqwqwotnqmqlsltlumwmym|nnonopoppppppppoqpqqq}pyqxotorpqopnnonononoonpnpnpnonnnononnnnmmmmmmmmlilimimhmgmgnencncmbm`m_m^m]l\l[kZl[kYkXkXjXk[k\k\j\j^k`jaiaj`k`ldkdmfoimjkjjjgigjhritishrhthvi{i~i}hzfzg{fyfublaiag`f`h`i_j^g^g]e^f_h_i^f]d\d\d]l]o^p]q]q\m\m^p^q]p]q]r]q\nZjZgZgZgZgZh[m]r^w^x^u]s]s^t_w^u]s]q\r\r]u\v\v[sYmXiXiYiWgWeVaT\SWRUrrrsrsrpqqqstsr~q{qxpurvruqtpsqtruqvrwqvprpspunvmvnwmyn{n~ppprqqqqqqqppppppqrrr}r|qwptqtprpopnpmpnonpnoonnnmnnnmnnononnnnnnnmmnmnlnlmkmkmjminimfmfnemcm`m_m^m\l\l\m[lYlXlZk]k]k]k_k_kaj`k`j`jalcmeohqknikiiihigljvjxjxirhqhsiyj}i~h|h|h|gzfxcobkaibkaj`lal_k^i^g_h^h_h^i]i\h\j]m]q^u^u]v]u\s]s^s]s^u^v]s\o[kZjYjZkZk[l\p^v_y_z_z^w_v_v`v^v^s^q\n[n[r[r[qZlXfWaVaWaWbV`U^T[SVSUsssstttssrrsttsr|r{rxrxswrwrvrururvruqvruruqvqwpxoyozo{o}opqrsrrrrrqqppppqqqrssrzpvrwrtqqqoroplpmpmpmpnoonnonomomonooonnonnnmnmmlnnnnnonnnlnlokpiogncn`m_m^m]l\m\lZl[l[l\l^l^k_kakbkak`kaj`ldnfohnhlhkhkklmjokvkzkxjqiohrivi{h{i}i}g{gyhwcpbkbkbkbmbnbpap`o`l_l_l`m`o_p_o]o]q^u^w^w^x^x]y]y^v]v_y_x\r[nZkZiZhZk[n[p]r^w_{_{_z_x_w^t`t^q]m]m\j[j\n[m[kYfWaU\UZVZU[VZTYTWSWSUssttuvuuussrsstts~r|t}t}t|tzswtwswsysztytxtyszszs{q{q{q~qqrrssstsssrrrrqrrrrttss}t{swqrqpqprormsmrkrkqlplpnpnqppppppppqpppoooonooopoqorpqooolojpiofododncnan_n`m_m_m_m_m_m_lalblambkalblblcnfnglgmhnhmimlmplulxlwjogmgqhtiuj{j~i}gyfvfrdmbibicnbpcqbsctbuasarar`r_s_u`u_u^u^x_y^y^z]y^z^z_z^z_{^x\r\o[jZfZfZh\n]r]u^x_{_{_{`|_x_r\k\i[g[h[g[i[k[jYgWcV_U[VYUWTVTWTXTWTXUZruuvvwwvuutssstttttuvvu|uztzt}u~t|uztztzu|t{t}s}r~rsrssuuuttttttssstssstutt|sxsurrsqsqrnrmrkrirjrkskqmpnqoqpppqrqsptpsqrptquququotqrpoompkpkpjoioinfnfoendndmam`n_m`mambmcldldkdkdlcmdnfohqkoimimmmnksnymvjnhmgphshui{ii~hzfsdmcibfbfdkdpcrdudxdwbvavau`v`v`w`x`x`x_y^z_z_{]z^y^y_z_{^z^y^u]p[jZdZd[h\l]s]v^y_y`z`z^x^s\k[eZe[eZd[e[f[fZeXdXcXaV]VYUWSVUWTXTYTYU\uuuvvwvvvvutsssuuuuvvwwu}v~xvu}v}v|u}wwv~u~uuvvwwvwxwvvvuuuttttutuuuutzsustttttsrsnsksjtjsitjskrjrjrkqmqoqpqpqqqrqrqtqvqwrvqvqtpqpnpnpopopopnomojphognenbn`nandnfnfmelelfldmdmcndmfpiphmimmllmrowmsjnhlhmhohuj{jjhzfpekcfcdcfcidndsdvewdxdwav`wbxayawaxax`y_y`z_{_{_z_y_x_x_y_{`|_z^u\nZf[f\h]o]u_x_y`y_y_w_s]k[d[dZc[cZa[aYaY^Y`YbYbXbV^V[UYUWUXTZU[U\U]vvuuuwvuvvvuttstutvxxxzww~xx~w|v}v~xyx~x|w}wwxxxzyyyyxxvvvuuuuuvuvuuvvuzuyuvtttstptmsjukujuktjsftfsfrgrjslrlrnrororrrsrururvquqrqqppprrtqwpvptopnloknhofoeoenfohohnfmfmemdmcmcmbmeoepgpjoknlnqotkqknimhjgkgqjzj~j}ixgqekcecdcgdkeneqdrdscucubtbubyaxbxawaw`x`x`y_|`{_y_z`z`{_{`~```}^u]k\h]k^s_z`|`|a|`z_v_r\k[e[d[dZbZaZ_Z]Y\WZX^YcXbW^W\W\VZVYV\V^V^U_vwvvvvwwwuvuutttuvvxwyzyx~x}x}w|x|xxxx~y|y}y~zyyzz{zzyyywwwwvvwwwxwvwwwvu}vzuyuvurvpumukvkuktjthtftfththtititktltltmsorpsrsursqqqqqrqtrzs|s|s{rwqtpppnplpjninioimhmhnhngnendmcmdndneogohpkplnlkmkojojnhkgkgnhriviuiufnejdecdbgdhdlencmcnbpbpbqarbtauav_u`v`v`xaz`|`{_z`{`}`~``aaa`{]o]j^mawa}aaa~a{_u_q^n\i\f\f[cZaZ`[_Y[XXX[Y]X^W]W\V[V[V\V^V`W`V`wxyxwvwyxxwwwvvvuvxyyyyzyx|x|w|x}yxyyz}z{z|y{y}yyy{{{{yzzyyyyxxxyzxwvxxwxwv|vzuvusvowmvkvkujuiuiujujvjujujukuiuhtiuktlsosrrqrprqrtsys}tt~s|rzqxqtprpqopolnjojoioioinhognfmflflfmenfoiqkqknhkhkllplpikgkgkgmgngngmfkehdeddcfdidickcjbkbmblbkalalao`r_r`s`t`waza{`{`za}aabaabba^q]m^p`wa}ccb|`s`r_q_q^o^m]i[c\a[`[_YZXYXZX\X]W]W]W\V\W_WaWdWeVcvxxxxwwyyzxyxyxxwyyz|{{{{y~y}x~xyx~y~zz}z{yzyzz|zz{z|}}|{{{{{{zyyzzyxxyyyxxww}vzwwvuvqwnwlvlvkvlvlvmvmwmwlvlvivhuhvkulupvqtososrsstvu{u}t}t}t}s{syryqvqupronomokokojojninhnhmimhmhoipjojngmgkglimmlpilhkglgkfjgjghfifgeeeeegdiejckcjclbkaj`iai`j`laoar`s`uawaya{a|a|b~abbbbbba_u_p_taza}bb~aw_m`p_r`s`v`t_n\e\d[c[_Y]Y\X\X]X]W_X]X^X_XaXdYgWgWguvxxxxxxyz{yyyzy{{|}}~~}zyzzyz~z|z|z}z|y{z{z|y{||}|~}}||||||||{zzyzz{zzzxww}x|xzwvwrwovnvmwnwowowowownvlwkvivjuluoururuststsuttuvzu}t~t}u~u~ttts|rzpvprpponpnolomnlnmnlnlonooooolnililimjllkoingmhlhlgkgifgghffddeffiekdldldlclclblalalbmaoaras`ratavaya{a|a{a}aa~a}bbbba`z`xazb}a}b}`x`s`p`r`rawayay_q]k\h\dZa[_Z_Z^Y`Y`Y`X`X_X`XbZfXiXjXhvuwxyyyyz{{{{{|||}~~~}{||{zzy~z}{}{~z|z}{~|{||}~}~}}~~}~~}~}||{{zz{zzyzyy~xzwvwtxtysxrwrxryrxqwowmvmvmvmwnvrwtvvvvvvuutsuuuyu|u~uvuwvvutsrzrwquptqspqoqpqoqpsospupuppnmmlmkmklnkoiojqjohlgkfighghefeffhfkfleldldmcmcococobobrbsatas`qar`tauaxay`waxay`w_wbbbaaa~a~b~b}b~azau`s`q`s`yc~ba{_t_p^n^k\g\f[d[b[cZaYaYbYbYbYbYeYhXjXjvvxyzzy{{{{z{z||}~}}}}}|{|{{~{}{~{{|}}}~~~~}~~~~}}||||||z{{{xx{xxyvxtxsyryrysxrxoxpxqxpxryswuwvwwxxwxwwusvrwtvxv}v~vwwxvwtttr~r{r|r}r|rzrzrzq{q{qzqzpvpqopnqopmplqlpkqjphmhlglgjgjfieifkflfmgofnendodqdqcrdtcubvbuaraq`q`r`r`t`u_s`t_r_r_tb|ca~a}bbbb~b}b~bzbxavauaycdcb}ayawav_r_p^n\h[e[d[dZdZdZdZcZcYdYgYjYlvwxyyzzz{{z{zz||~~~~~|||}|}|~}}~|~~}~~~}||}|}}}||zzx{yyxwxuzuzvyuxtytxtwtxuxvywywxxxyyzwzwwvuwuvtvvwzv{v}wxxxwvutsssttsssssssr{qvqvpvototmqlrkrlriqhrishqhpgnfnfmflfngqfrfqdpdqcqcscucvcxcwbtar`q`q`r`q`s_s_s^p^o`q`uayaza}bccbccb~b|a{b{cedcb~b}c|bz`x`w_s]m]j[i[i[h[hYdYdZdYdZfYiYkywwxyyyyzz{{{z{||~~}~~~}}}~|}|}}}~}~~}}~}~~~}{zy~y|y{y{zzyzyzyzyzz{z|z|z|yzyyy{z|y|wxwwwvwwxxwyx|xxxyxwwvutttttssttttsr|qxrxqypxovntmtmtltktjujuhuiuiugrgpfogqgtgvgtfsfrercscvdxd{cycvbtas`q`o`p`q`s`t`s_q`q`s`v`za~cccbcdddddeeedcccb}a{ay`x`u]q]o]n\m\jZfZdZe[gZh[k[l{zxyyyyyzz{|}{z}||~~~}}}}}~}}}~|{{zzzyz{z{{|{z{{z{{y|x{xywywxxzxyyyzyxvvu{t{s}tuuustttstqzqxqypxpwntounultltktjtisivjwjyhwhtgsgrhuhvgugtftereretdwdze{dxcvbtas`ras`s`vbyc|aw`rasawb{ddedceeefeeedeeddcdb{ax`y`y_w^s]q^p\m[h[g\h\g[g\i[j|}{yyyzzz{z{|||}}|~~~~~}~~|{z{zz|||{||||{|{|{zzyxzxzxzyzxz{zyxu}txswt{t~tuuuut~s}s}r|qxqyr{pvornpnrmrmslulukrjqjujxiwjwhthrgqhthufsgqfqeqdqeseveyezezdwcubtatavbxb{c~cbyaubwczdddddcddeffeeeedeedc~ax`vaway_x^r]o]p^m\k[i\i\f[e\hZe}~}zzz{{{||||}}}}|~~~}}|||||}}||}}}|{|{z{{zy~z~y~yz{{zyzxu{vzuytyu}uuuuts{rxryqxqxq{r|pvnqopnpnrmsmrnsmpjrkviuisithtgogngqgtfpfofoeocncpeugyfzexdvbsbtaubyc{c}cca{bxbzdedeeedddefefeeffdedc{auat`t`t`t^o^m^p]p]n]l\i[f[g[eYc{~}|||}}~~|}}}|}}~~~}||}|}}|}~}~|{||}|zzzyzz{|zxw}w{wzv|w|v|u~vvvtt|rwqvqvqvqypxqxotnrornrnrnsmsmqnqmvlvithrhriqgpfogqgqgoemendndndpetfvevdvevcrcscucyd}d~ccc~c|d|defffffefeedd}dfffecb}av`r`o_o^m^l]k^l]n]p]n]j\gZeYbYaY`|~}}~~}~~}|}}}}~~}}}}}|~~~~}||}}}{{zzz{|{yx}w{xzw{wvv~uvvut}tzrvrvrwrwqwqwouotororososnrnqnrmsmtkriqiohohphphrgrgqfofoeododoereteududvdvcrcrdtcwe|edddedeffgfefeedddb}ceffdb~ayat_n_m_l_k^j]j]k]k^n\j[eZdZcYbY`Y^}~}}}}}~~~~~~}~}}~~}|{|{{||{y{wxwvwwx|xxwwvvvu|tysxsxryqyqypxovouospspuotornqnpnrmqjoimjnjohqishshtgtgrfqerdresftftdrdtcubtbscrbscudzdeeffeffgffgged}d~db}c}ddefcb{aw`q_j_i_k_l_l^l^l^n^p\i[d[e[fZdXaY`}~~~~}}~~~~~~}||{|||{yyxuwtwvx|xxwwwvvu~t|t{s|s{s{q}p|pyoypyqwpvpunsnrmqmrmrjoinkpjqjsiuivhwhwhuftftfteufveudrcsctctbrarbtbwczeeffeffffffefe~dydzc{d|czd|eecbzaxatar_m_k_l^m_l_l^o_p^n\j[e\f[gZdXaX_~}~}~~~~|}}||z|xwwuxwyzxyxwxvvvutttsrrq~p}qzqwpuotounvnumumtlsltkukvjvjwixhygxhwgwfvevewfwetdsesdsbrararbvbxd}deefeffffee|e|d{cwcsctcubvcxd{d~eczbwawavas_q_o^n_o_m^n_q^s^q\l\hZgZgZeYaW_~~~~}~}}|{z{xyxxy{y~yxxww~wwvuuttssrq~pzpwovntovnxmwmxnznymxm{lzkzkyjyixiwhxgwfwfyfyexetdrdrdrbrarasaub{ceegeefddeee}dydxcrbpbqbpapcscwdzdycubvbwbwau`t`r`r_p_o_p_t_u^t]o\k[j[iZfYaY`}~~~~~~}|{zyy~zyyyww}xwvvutstsrqp}o{nxnvowozo{o~oo|nzn{m}l{kzkyizi{hyhxgyg|g~f}dzdwdwcubsctataub{dcegfdeeeffe|ewdscnbmaoamaobocrcrcqbocubwbxbz`v`u`u_u`t`w`x`w_v]t\o\lZiZdYcXb~~~}{{zzzyyxwwxxwvvuttsrqppo|nynyo{pqqrq~m{n}l}kzkyizj}i}h|f{ghhffd|czcycwbtbwc}ddfffeedeff~ezducobkalbnbobnboboamamblbqcxc{b|bzazazaza{a}a|`{_y^v\q\n[j[g[fYe}|||{zzyxxxxvwvvuuttsrqooo~o~pprssro|m~m~l{jxizi}ih~ghhiihfee}cybwbxb}degiffedff~evdtcpbkbjblbmbnbnbnamambmbmbocwc}dcdcccbba}`z^w^u\q\l[e[d[f}~~|{{zyxyyxxwwvuuuttrqonnppprttso|n|m~m~jzh{h~jgghijjiiefd}c{c}deghhffeef|eudqdqcpcnblblbmbmcobobobpbpanbocwc}decddccba`|_z^x^u\mZeZc[f~~~~|||{zyxyxxvvuutttrrppooooqssssp{n|m|k|j}i~iihhijijjkjhfedeghhhgfeeeydseqdqdqcpcpcocococpcqbpbobobpbrcwdeedddbccaaa}`|^w\r\j[f[g~}||||zzzzywuttt~ss~sqpppoopqrqqrp|n|m}l}kijijjjkllklkjhgegijjihffgeyeuesesftetetdsdsdqdsctcqcncobocsdxd~eeeedccba~a}`|`|^x^r]n\k\l}|}|{zzyyxwvuts~strqrqqpppqpopqpommllllkkklmlkkkkjhfijjiihhfhf~fzfwgwfwfwfweveuftewevdtcpbqbrbtcvczeedccdc|bzazax`z_x`v^s^o^o^r~}}}{{{yyxxwvtttssrssqqppoonnopoonnnmmmlmkkkkkllkjiijjiihghhhgg|g{gzgyfyezfzeyfxevdscqcsbsctcvczeedccc{avavawawaw`w_w_u_t_s`v~}}|{zxxxwvuttsssssrrqponmnmnnoonnonmnlkjjjllllljjjiiiiiiihhhhi~f}g}f}g|fzfxevdrcqcqbrcucxc|dd~b~b|bzbwbuaubwawax`z`yaxax`v`v}}||{xxxwvuutssrsrrrqqpnonnnnooppppomlkljjjklllljjjjjikkjiiiiihgggf|eyevdudscqcqcuczd}d~b{aza{bxbvbvawbwbyb|b|b|a{b{bxau~~}}{yxxwvuutttsssssrrqqqppoppppqqrqnlkkkjjijkllkkjkjklkkkkjjjhhiihg~ezewducscscvbyc}b}a|a|a{bybyayb{b{cddd}c~d~c|b|~~}}}zyyzywvvvwvvuuttsrsssrrrstrssrqqomlkkjkjkkmnmmnmlllllklkjjiiijiif}ezcvcwdwcybyaybza|b~b~c|b|b}cddeddd~dcc~~~|{zyzzxwwwxxvwwvtutttusttuvvsrqopnmllkjkjklnmmnnnnmnmmmllllkijjiifd~d|d{c}c~b~b~a}bcccb~ddeeedec}c}de~~~}|{zzyyxxwwxyxxxwwvuvuuuuwwxvtsponmmmmllmmnmnnnnnnnonmmmmmmljjkjiigffeedccbccdceeegffedc{d|d~d~~}||{zyxxyyzzzzzxxxwxxwvvwxxxvutronlmmmmmnopnnnponmnnnmmmoomllkkjjighgfeeccddeefffefffee~e}e|ee~}||{zyzyyzzz|{zyxyyxyyywwxzyvvtrqononnnnopppoooonnnonnnoonlklkkjjiiiggeeeddfeffgefffffeefee–••”~~~||{z{zzz|}}|z{{zyy{{zyyyyywuutsrqppopqqrqqqppponmnnpppollkklkjjkjigfefefgghhhgggfgggggfe}e~›˜˜ØėÖĖĖÕՖ•–}}|}{{|{}}}{{{{{yy{|z{zzz{xvuuurqrqqqrrrqqqqronmnooqqomljklmjjklkjgeffggijjkihhhhihgggfee}œœœÛÚÙÙÙĘŘŘŗŖŕ֖–Ö—×~~}||}||}~~~}|{{{zyz{{{{||{ywvuutssrrrrrrrrrrrponopqpqollkklmlmlkkhgghhijklkkjiiiijihhhggežĝÝĝĞÞÞŝĜŜśƛěŚřŚřƙƘŘĘĘ××ė֗—}~~}}~~~~~~}||{{z{{|{{z{{|}zywvvusssrrqqrrrrrrpooqqoponml}llkllmkljiiikkkkkkkllkjkkkjjjihggžÞŞŞŞŞƟǞŝƝǝǝƜǛƚƚƚƚǙƚƚŚƙŘĘėĖÖ×~~~}~~~|{|{|||{{{|}}|ywwvuurrsrqrrrrqrqrqppqpppmm~m~llllllllkjjjllkllkllmmkklljjjihggÝĞĞŞŞƞƟƟǞǞƞȞɞȜȜȜƜȜȜȜǜƜǚřƘĘĘė×Ęė–~~}~~}}}}}~|{{{||||{ywwutsrsqqrrrpqsssrrqqppomm~mlmlllkmmmmjllllllmmmnnllmlljjkjiiŸğŞŞŞƟƞƟǟǟȟɟɝʝʜʝȞȞɞȝȝȝȜȚȚƚƚƚƚŚƙřė×~~~~}}}||}|}}{zzxvtssqqrrrrqqsttsrqqpoonooonmmmlmnnlllllllnnnnonmmommmmkkjj àĠĠƟƟƟƟǞǟǠɠ˟˞̞̝̞̞˝ʟʞɞɞɝʜɜɜɛȜȜǜƚșƙƘŘs5"1tX{~~~~~~~~~|}}|{{yxvuttrssrrrtssttssrqpooooopommmonnmmmmmoopqoonnnpnnmmmlllláġŠƠƠǟǟǠǟȟɟʟ˞˞͟͞Μ̟͝͞˟ʟʞʜʜʜʜɝȜȜȜȚȚǙƙřØB-By~}}}}||yxxwvuustssuuuuttsrrrppopppppponnnommnonopqqpoppqppoonnmmml¢âġơơǡǠǠǠȡȠȠɟʞ˝̞͞ΞϞϟ̞̟͞˟˞̞˝ʝʝɝɝɜɛɛɛǛƚƚ٘I5L~~~}|}}|{zyxxxvuuuuttvwvwvtsssqppppqqqqpppoonoopopqrqrrrrrqppppnooonãŢǢǢǢǡȡȡȠɡʠʟʟ̞̞ΞϞϟϟϞΞ̟͞˞˞̝˞ʞ˞ʞʝ˜ʛȜțȜǛǚꘗK4L~~~~}|||{z{zxyywvvuutwwwwvuttussqqqqqqqqpqpppppqqrrsrssssrqpqqrqpppo¢âĢǢȢǢǢȡȡɡɡʡˠ̠͟͞ΟϟРПϟϟϟΟΟΝ̞͞˞˞ʞ˝ʝɝɝɞɜȜǛƛřØK5K~|}||}||{zyxxxwvvvwwwwvvvvussrrrqqqqrrqqppqqrrsssssssrrsrrrrrqqpãâ¡ šƣǣȤƢȢȡɢˢ̡͡ϡϡРРРСϡСРРϠПϟ̠͟͠˟ʞʟ˞˝ɝɝɝȜǛƛٙM5J~~}}}~{|z{yyxwwxxxxwvvwwwuuututtsttttrrrrsssstssssstsssrrrrrrrqƤƤǢơġŸŸŸßšǤǢȣȢȡɢ̢̢͡ϡТТңҢѢҢѡѡѡСРРϠΠ΢̠̟͟˟˞ʞʞȝɝɝǛƛÚL7K~~~~}}|{zzyyyyxxxyxwvwwwuvvvuuuvvvvtsstttsssssrsttutttsrsssrrrǦɥˤʣʣȡơĠġšơǢȢɢɣʣ̢͢͢΢ТТңҤҤҢҢѢѢѢѡССϠΠ̟̟͟͠͠˟˞˞ɞɞʝțŚ™-)ye~~}~}||zz{zzyyxxzyxvwwwxvvvuuwwvwvuuvuuuttsstttuutttttsssssrrǧɦ˦ʥˣ̣ʤȣǢǢǡǡǠǠɡˢ̣ͣΣΣϣѣѣҤҥԥԤӤҤӣңҢѢѢϢΠϡΠ͠͠˟˟̠ʟɞɞɞȜśšš™"eS~~}}}}{{{{{z{{zz{|zxxyyxxxwwwwxwxwvvvwwvvttuuvvvvvvtuttstutssȩʩ̧̦̤̤ͦͤʤɣȢǡȡɡɡʡˣͣΤϤϤФѤҤԥԦԦԥեԥԤӣӣңѢТϡϡϡ͠Ρ̡͠ˠ˞˞˞ʝȜǜŚšěœ›&%uh~~}||||{|{|z{|}~~}}|{{{zzz{yxxyywxyywwxxwwvwwvwwwxwvvvuttuuuttȪɩ˩̧ΧЦΥͤͤʤɣɢʢʡɡɢˣ̣ΤϥϥХѥҥӦӦէԦԦզեԦեԤӤӤѣТϢϢ̡̟͢͢͟͡˞ʝɞȝǝĜÜÛÝşŸ%$dW~~~~~}~}}{|}~}||{|{||{{zzyyxzzzyxxwwxxxyyywxwwwvvvwvvuuuȩȪʩ̩ΨЧШЧЦ̥̤ͦʢʢˣʢ̣ͤΤЦѧЦѦҥӦӧզէէէզեեեԥԥԥӤҤңУϢΡΡ͠Ο̟̞ʞɞȞȞƝěŝĝƞƠġ '%h\~}}~}~~}}|~~}~~~~~}}{yzzzzzyyyyxxyyzzyyyyxxxxxwwvwvuɪʫʫ˩ͩΨѨѧѧѧϦͦͥˤ̣ˣ̣ͣΤЦѦҦҦҦԧԨէէ֧֦֦֦֨զզ֥զզԥҤӥңУѢТΡϠΠ̟ʟɞɞȞǜǝƞěÛƞǠǡšáp"A2L~||}}}}}}}~~~}{|zzz{zzzzzzzz{{yyzzyzyyyxwwwwxwǪɪ˫˫̫ͪϪЩѩѨѧΦΧ̦̤̤̣ͦͤΥЦѥӥӦԨԨըը֨֨ק֦֦֥צ֦զզեզեԦԥԤӣңТϢΡ̟˟ʞɞʞ˟ʟƜÙǞȟɡǡơšà u^-!2~}}}}}~~~}{|{{|{{z{{{|{z{{zzyyz{yyyzyyzzzƬǫȬɬ˫ͫΫΫϪϩϧШШϧΦ̥ͥΥͥϥϤХѥӦԨ֩թ֨֨ררקצاب֦զԦզ֧էԦզԥԥӤҥФУϢ̡͠ˠʟ̠̠͠ʟ̡͡ˢʢǡǢġ¡ZGj:*> M@ay~~~~}|{{|||{{{{||{{zzz{{{{{{|{|{{z{ūǫǬȬʬͫϫЫΫϪЪШҨѨϨϧϧϦΦХϥХХѦӧ֩֩֩רש֩ابקبר֧ק֦էզ֦էզեԥԥԥҤҤѤϡ̞͟͠ТТѢУΣΣ̣ʣɣƣĢaOu)-"$#B6Xwd}~}~~}}{|||{z{z|{{{{{{|||}||{{zƫǫƬƫɬˬ̫ΫΫϫЪѫѪҩѩЩϨЧϨϧЦЦЦѧҧӨ֩֩֩שתתשש֩שة֧֧֧֩֨էզզզզզզԥӥӤѢΡϠТҢңѣУϣΤ̤ʣǣţJ;`  zh~~}||||||{{z||{{{|}}||{{{{ūƬŬŭȬʬʬˬ˫ͫΫϫѫѪҪѩϩϨϩΨШϧЧѨҨӨ֪֩֩ששתتةתةש֩֩ש֧֧֨֨զ֦էէէզԦԦӥӤңѣѣңѤѣФΤ̣̤ɣĥ¤?6b   +  dU~~}~}}}}{{yz{|{z|{|{{z{||{ǬŬŬƬƬȬɬɬˬ˫ͫϫЫѫѪҫЪЪѪѩϩЩѨѧҨթթ֪֩ת֩תתתتשתתשש֨֨ר֧֨֨ק֧է֨զզեզԦԦӥӤҤҤФϤΤ̤ʤƥ¤*+ MAf~~~~}}|{yz{{{zz{zyy{{|{{ǭǭƭǮƬǭǬȬʬˬ˫̬ͫϫЫЫѫЪѪЪЩЩѩҩҨԩժժ֪֫֫תתתתتתתתثתשששרש֧֧֧֧֧֧֨֨֨֨էԧӦӥХϥΥˤɥƥ¤xm(%!##$" ?/I~~~~~|{{|||{{{{zyzz{zzzȮɯȭƮƮǭƭǬȭɬɬɬɬˬϫϫϬЬѪЪЫϪЪѩҩөԩժԫժժ֫תת֪֫תתת׫תةתשةשר֩֩ը֨֨֨էר֧֨֨էӦҦϥ̥ͥʦƥåma'"%!$ % %##/"2}~~~{||}}|{zzyyyyyyxxxǯǯǯƮƭǭǭǭȭǭȬǬȬɬɬ̬ͬάάϫЪЫЪҫҪԪӪԫիժ֫׫׫֫׫׫֪֫׫ثثتتتשתتת֪֩֩֨֨ררשרררէҦЦΦ̦ɦǦpd  +  &%{~}{{|}|||zyyxwwvvttsǰƯƯįŮƯŮƮƭŮƭƭƭƭƭȭɭʭˬͬЫЫЫЫѫѫӫӫӫԬի֫׬׬׬ج׬׬׫ث׫ثثثتתث֪֪֫թԨը֩֩שةששըըҧϧͨʧƧ¦wi   +  %%~}}{z{|{zzwxywwtrrrqoưǯƯŰįĮŮŮĭîĮĮĭĮŭĭĭƭȮˬͬάάϫϫϫѬѫЫӬԬի֫׬֭׭ج׬جج׬׬ح֫׫֪իժ֩ԪթԩԨըժת֩שթԩԨѧϨͨʨǧçr$  (*~|}|z{{{zywvuutusrqpnmȱDZǰưůůİİįð¯įî®®îíĭŭȭɭ˭̬̭ͬͬάϫϬѬӫԪլ֭֭֬ج׭֭֭֬֬׬ثתի֫ժժԪԩԨԨԩԩժ֪תש֩ӨӨѨΨʨǨħiX0$<r~||{zzyyxxwttsqqqpnnmkʲȱDzƲŲűıññ¯¯¯°®®®íĭǭǬɬ˭ʭʭʬ̬ͬϬЬӬԬԬ֭֭֭֭֬֬֬֬֫֬֫իժԪԪԩҨөөөԩժժ֪֪ԩөөϩΩɨƨè| ,1~}{yxxxwwvuurrqooonllkjʲɲƲŲƲIJò¯îŭŭǭȭǬǬȬʭ̬ΫϬҭӭԭխ֭լ׭֭׭֭֬֬ԫլԫԪӪӫҩҩҪҩӪөӪժժԩөҪϪ̪ȩè#"2'>|||yywutuutssrqpoonnnkkii̳ʳȲȳDzDzŲò®­ĮĭƭŬƭȬʭˬͬѬѭҭӮԭ֭֭֭֭֭֬֬լլիԫԫӫӫѪѪҩӪԪԪժԪԪӪѪϫʪƪ©(#  +  TGm~}{zyxvvutttssqqppooonmljji˴̳˴ʳȳdzƲIJó®ííĭĭǭȭʬͭЭҮӭӯӮծԭԭԭխխլխ֭լԫԫҫЫѪѪҫԫիԬիիҫѪΫ˫Ǫ©$#!  ]Q|~~|ywxvutsrsqqppooonppnmkkkdzɳʹ˴˴ȳȲųijó®­íĬƭȭͭϮѯҮѯүӮҮѭҭӮҭԬӭӬӬӫѫЬϫЫѫҬӬլլԭӬЬ̫ɫŪ%!*/&"$$SIo~|zwwvuusrqpppppoonooponmllŴƴdzʴʴɳȴdzĴô´­¬íĭȭˮήήϯϯЮЮҮѭҮҭҭӭҭҬҬѬЬϬЬѭѭӬԮծԭҮѭέʫƫª** .#8ZNv~}{{yywvuutssqppoopppooonnnnmlĵôĵƵȴȵȴɴȴŴĴ´¬­ĭȭʮˮ̮ͮͯϯЮЮЮѭѮҭҭѭѮѭέέͭϮѭҮҮӭӭҭѭάʫƬë') "@6U}||{zyxwxwvvttsrrqqqppqpppnooonllͶöĵŴǴƵȶǵƵŴõ­íîƮȮɮ̯ͯͯίϮϯЯүѮѮѭЭέͭ˭̭ϮϯҮҮӮҮѮϭ̬ʬƬ«, 1#"#90K~~}|{zzzyxyxxwvtsssrrrqqoppqpoonnmmkĶööĶƶƵŶŶƷƷŷĶ­­®®ĮƯɰ˰˰ͰΰϰаЯѯѯЯЮή̮ˮ̮ͯЯѯүүЮϭ̬ͭɬƫ«%% +""7-H~}|||||{{z{{zyywvutssssrrqqpoonnmmlkjǸƸĸŸŸƷͶ·¸ïůǰɯʰ̱αΰΰΰϰϯίίίʮ˯̮ίϯϯϯήͮˮʮǬī«{ $'+1$(}~}|}{|{{{zzyyyxxwvvussssqrqooommlkjiiȸǹǹĸŹƸŸĸ¸İŰȰ˱̱̰̰̰̰ΰΰͰͯʯȮɯ̯Ͱ̯̯ͯʯȮǮĬ¬~u8,H(,"!*!5"#~~~}}}|{{{{{zzyyzzzyxwwutsrrrrqpponmlkjjiʸɹʹɹȹǸƹĹĺıƱʱ˱˱ʰɰʯʰʰ˯ʯɯȯȮɯʯ˯ɮȮȮ٬wp%. "&."6~~}|}zzyzyyyz{||{{zxvvtttsrrqqqqpoommlkkͺͺ̹̹˺ʺȺƺĻúº¹ıŲȲɱȱ˱ʰʰɰɯɮȯɯɰɰɰɯɮǮƭí­oi#& %,&/~}}}|{zyyz{{|{zzxwvvvttsssqpponnnmlmmλͻͻ̻˺ʺȻƻƼĻ»»IJDZɱ˱ʰʰɰɯǯǯȯȯɰɯȯǭĭ¬gaA:`.$;%""&=6[%+~~~||{{{zzz{||{|zzyxwwwvuttrrqppponmmlnξͽ̽ʼʼʻȻǼȼȼżļ³Ųɲ˲̱ͱͱ˰ɱȰȯǰȰȱɰǰůï_YD=i#%(17-N|~|zzz{zyz{}}}|{{{zzywwvutttssrqpomllk̾̾˿̿˼ʼʼɼ˼ʼɽǻļ»»ºIJȲ̳ϲггϳͳ̳ʲʱȰȱȲȱǰįï®êª[Rz+ 2 +(382Wtv~{{z{zzyz{|}~~}{{zxwvvuutssrpnllljʽʾ;ξ;ͽʽ˽̼̼˽ɽǽżļ¼³ijƳɳͳгѴѴѴϳ̲˲ʱȱDZűƱŰï¯UKn/%<(-!* 4.%?nl~}||{{{{||}~~~~|zzxwvvvuvtsqqollj~gʾ˾̾ͿοͿ̿˾̾ͽ̽˾ɾƽĽ¼óŴǴȳ˳γгѴѴдϴʹ̳ʲDzƲűŰİïMCaQHx"$"$)) 6he~~}}|}}~}||{{zyxxxwwwvtronl~k|izgɾʾ˿˾̿̿̿̿˿̿̿Ϳ˾Ⱦƾ¾óŲȳɳ̴ʹϳгҴѵѴѳϴ̳ʳƲƱƱűŰŰïF;VD>c  , 4>3Xda~}~~~}|}||{zzzzyxxwtrrn|j{iyhvdƾȿʿʿʿ˾ʾʿ̿οͿͿͿȿſ¾´Ƴɳ̴ʹϳϴѴӴӴѴѴдͳ̳ȱűŰƱǰȰűï?5J(-, 2" *!2HAj[U~~~}{{zywvtpo~o|m{ixfueteĿſǿȿʾɾʾʾ̿˿ϿѿҿѿοǴʵ̶εдϴдҴӴҵҴѴϴʹʲDZƱŰDZȱDZűİ@5MZT-"4%""!=4S6+FYPx}|zxur|p|nxlykvhuescqcocĿľſžƾǾɾɾʿ̿˿ѿֿտѿĴȵͶͷжжѵѵгѴҴӵҵѵг˳ɲƲűıİƱưݯ>3KC;e!4)EZPz~|zx~u}r{pzmxkvhvgtdrcqcnambĿ¿ÿľƿǿȿɿʿοѿҿӿǵ̶ͶϷзѶѵҶҴҳѳдѴѴδʳDZŰŰððİİű°>5M3)B " &)@8WSHj~{yy}u|s{pynxlvjuhuftdrdpcocmcƿƿƿƿͿѿ¶Ƕ˷θѸҸӸոշնֵҳϲϲϴʹ̳ʳȳƲƲƱƱƱűñ°5+>;1N2(@$"3';\RM?[}{}w|v{sxoymxkvivhuftfscsdrdrdpd¿Ŀſɿŷʷ͸ѹҸԹֹ׸׷׶ֵԴѴβδεδ̴ʴɳȲDZƲƲűİðI<[kg/$9'(%$KAb8,CUEb|y|v{uxsvqunslsjthrfsftesesdtercrdķɷͷиҹԸո׸طֶնԶѵͳɱɱʳɳɳDzDzdzƲƲŲűñ®S}{{zvxsvqsqropnonnipgqgqfqerfqeqfqepdŶɶ˷ηҷӹոֶ׷ַշӶдͳȱůűdzDzʳʴȳȴȳƲƲı±°İŰİï¯FQªªëìĬŬƫȫɫʭʬʫȫǨ}{zxv~t{rwrvpsopnononnmmkjmiminingnhmhnhkfkfѿѿøƷɷʷ̷϶ѶԷַշҶѶдδ̴ʳƱįDZɲɲdzDzdzʳ˳ɴɳɳȲdzŲıİưȱɱɱDZ۰¯SGgmc2$6'$&%OA[?0AcPiŭȭȮɮʮʮ˯̮ͯͯήήϭά˫ȩŨ}{xwvuut|syrvquptornpmpmpmolnlmlmkmkllkllklkkjlĸɷɷ˶ζзҶҶӷҵѶдʹʴɴȳưůDZǴDzŲDzʳʴʳ˴˴ʳȲƱIJƱƱȱȱDZűݰF=XZOw, +% "$ A1>dPdȭˮ˯˯˯ͰͰͯΰбаѱҰҰаήʪƨ~{ywuutt~t|syrvquosnrnqmqmqmqlqlpmomoknknjninininƷʸ̷ηзҷҷԷҷҶϵ͵ʳȴȳȳİįDZȳdzDzDzDzdzʴʴɲDZűűƲƲűűűðİB5NJ?[- +  -(bM\U@Nʯˮ̯̰̰̰̰̰αϱбѱҰұұӱѱ̭ɪħ|zxvvtst~s|ryqvpunsmrlqlrmrlpkplpmpkojojojpiphphpƸʸ̷ηиӸӷԷӷѶжε˶ɵȵȴű®®ïİıï°IJƲȳdzűıŲƲDzƳƱƱİï9-@:,>3$1$bN^t\jͱͲͱ̰˱˱ɰʰ˱̱̱ͱαϲѲѱҰҰϮʪǨŦĤģ}zxvutsrq~p|pyoxnvmululslsmqlpkqjqkqjqkrkrkrisisirŸɸ̹θиѹӸԸӸԸѶ϶̶ɶǵƴŲıî¯İñ±ñı±IJƲƳȲȲƱİð}[Jdwe9)7'#$?,9OrlA6N'#5(8!rg|o\Lg|ywvusrtsrqonoprtwx{}~~|yzzz||||Ϳ˼ʺʺɹǸŷµ´²4#/XIcA1B&%)$:,< /#0PC`6'7}zvtsrrrqqqqqstuuvy|̽ɺǺźŹĹķµ*$A4@`Sm5*8(#+)'%N?W;-=s{vsqqqqqqsvyz|}}}̿ɽɼȾŻúù¹y*(UF^H9N, +'$$ X&"C8MA5E|wbOd++uxsu?4H'%* * l`hWn*+\^HCf7-B. , , )("L?U>0@PDYF8Ms!>9WFEkEBc* -#MD_% $ YOmB4I6+6qdx~=9XF?dFBc))6-:QD[M@TOCT^Qgjk-#5mrmo=3H'#SKcpdxvxcSc~}}}]Xz<1GXMi?3F/#-[Rl3&1M?Q{{iUe~}}|}~~~~SJcH>P|^Rjk^z5&3'#0$0.*H,'/ ),&*$,%*#2#.&!$+#^QdĶķķŷöö³ĵȺɹɻȻɻǻǻƹǺȻɻȻɼɼɼɼ˼ʽʼʼʼɻɻɺǸǸȸƸƷǶƵŵijó²|{{{{{{{{{|{|}}}~fa,'&"%$- &7)2. +1!+5$/.'5%1$"$&J=JµµöķƹǻɼȼǺŸķʽʾʿʿʿʿɿʽɾʿʾ˿ʽʽʽʽʽ˽˽ʾ˽˽ʼʼɼɼȻǹǷƶƶŵóó²{{{{{|}}|}}}}~~~XQl/!'%$- ( $ ,%"*"!;-7¶öķŷŸŸŹǺǻǻŻźķ÷źɽɽȼȼƹķǼɿʿʿʾʿʿʾʾʽɽʼɽȽȻǺƹƸöô´³{{||}}~~~~|rE8G-%*#'% *$ $"&!'%&%+"teq·øŸĹĹĺźǼǼǾȽȽȽȼƼǽȽǻƻƻǽȿɿȾǼ·øʾʿɾȾȽȽȽȾɾǽȼȼǼȾʿɿɾʾɽȽȼǽȽȼǻƺŹĸöö{||}~~~~{NCR&)##(&)$.&$'$;8K;.9=-8G8DJ28:.4- (%"&."&,&|4'/' /"(&")"A6CC8?- &$0$)*#( bZgi`sPES!4(0"+!%+&!ZQ][Sa\Sd]TiYRi[Uh`ViC6C!!8*30%+5(->2:VHZA5@MBP8,9=1=>2=.!*4%-cYr%%/#+@6@:.74%0y{?3B4&1aYo=3@.#*3(/2$0E;Hme4&0()3'-=1<0",rh~}~}zz|}|~~ts+ )5*6OF]1%--!(-(0".WO`x6'1&-!%<074*0=0;K>J}~|zzzz{~}{z{{{{||{|{}~RI^:/9:/:PGX. (7+4'!,)mg~7)1'8-5PFQNEQ0%,4%/}{yzz{zz{z{|{yxxwwvvuvvvxyyz{{|}<1?bYn-!(;.8("3(0/!)*%{?/=##:,4@4?90;.!)}x}|{{|{{||{yxwwwxwvuuuvuvtttuuuuuuvvvwvuvwwxxy}wrA4D\TjG=L/ *>12TVNh3&/H;M+ (4'26)38)7B8Iog;*5) 6*35&/8,5E9E6)5~~|z{yxxwvvvuuuututtuttuuuuuvvvvwwwwxwxyz|~~~|}}{yyy{|z{{{{{z{y{zzzzzyzzyz||}~{~7*;.+4(54)53(57,94'20"-IAX}6%/(>4CQGZKBS/$+("pj}|}{zzyyxwvvvuuuuuvvvvvvwwwvwvxxz{{zyzz|~}|zzzzxwwwwvwwvxwwxxxxxxywwwxxxyzz||}}~}~}~~ikQJlA7O9.><4G0#00&38,:*'OHd9)3$+ %@3AG:I8.:'#NEY|{{yxxxxxwxyyyyxxxxxyyyzzz{{}~~~~~}}}|{zyzyyyxvuvvtuvuvwuvvvxxxxyyyyy{{|{|||}~~~PLphm,"-5):4'8B>]A;R8)6.$/[X{I/>E9HH@U2$-~~~}}{{{zzyzzzz{zzz{{{{|~~~~~}~}{{xwwvuvvvvvuvwxxxxyyy{{}~}~G1A0%2y|pn6&/*%6,9A6HF=QD:M>1AL@U~}}}}|}}~~}~~}}||||||||tuvxyz{{{{{zzzyyzzzzz{|}~~}NC^4%27,<9->5(65H4)68.?0$..#,?4FxxD6F&;0?QJeWOnMD],%7,8f_~~~}~~~~}}||{{{zzustrruuuuuusrrrsrsttuutuutsrrssrsrrrtvvxxz{{{|}|~}}~~~~~~~w|xzw{_\7)6H?V1$-0"+1#,+%,&6)4+)3(7F;QH=TH=UG=RE;OC7JD8LF;OF9MB4H>1EC6KC5F*%& ,$1"*0"*)".!*C8Ie`fbhe~~~~}~}~||}{|zzzzzzzpqpoqrsrrrrqrsstuuwxwyyyzzyxxwuusstssuuuwxyxxwwvvxyxwxy{{zyxwwxy{}||~JLn$#(%+ ),+#+%. &/$3!(% &!3#.F5KRCaPA[PAWF8MULmPB[ND^G4BL7HM9MN7H@/=?4C#2*8-#!'')!%%!81B~~~}}}||{{{{zyyxxxxopssutttuttutsttrvvuuututtsstuuuuwwyyyzzz{||}~}~~~}~|~}}|{|zz{{|}~~~~}~~}~~ZbBDf"% +&& 6&/7&++ /%#"3#+M9JS=OP;MN;MI5GS;OR=SO6HN8KS,;:'54%.,%*"&-'*$' '!/ )*$.!'7+:<4H~~~}}|}|}|{{{yyyyxyxwvvvvpoqprsurqsrqrqqqrqqrsstststtststtuvuuvuwxyy{|{|{||~}~~~~~}}||v>8S5'55'23%03%/1#.1%/1#-2".1#.2$.0!,0",- '.!)- (,&. )- '/!). ',(- (-)-(. )-'0!+,'-!(+'- (*'0!*. &0"*."+, )p~~~}|{{{|{{zzzyyxwvwvvvuttsopqqqqqrqqprpqqpqqrqsrpsrqqrqpqoqoppqppqqqqrtuvvwyyz{||}}~}}~}}~~}~}}}{z|}}|~|}}z=;X  ! !  !!!!$ # 3.Dsxy{{||~~~}|||z{zzzzyyxwxvvvuuvutttsllmnopppqqqpqrqrsssrssrrsqrrsrssrqrqqrrqqqpopoppqrrtwxwwvwvvvwwvwwyyxxxwxxyzz{{|{OT-"1) ,,".('+ +*(-!,))+!,* *,!,* +) ** (*(*((''&&&*)'%+ +)',"+((-!-('."-)(-",)'.$.)%/%0,!,2'3F?[}}~}}||{{zzzzyyyxwxwwvuuuuuttsssopoqpppprrsstssttsttsuttvwuvwvvvvvvuvwwxxwwvtqpnnpopqsrrtrsrssrstuuvuuuuuuvuvuvuvMV3'4/$0/%1/$./#//#.-",.".+!,)(*))')&(&'$%"%"$"&#$"&"& (#%"'&&#(%&"/#.,)."-+(1#,-!+0#.0$.C;Q~~~}|}||{{zzzzyzyyxwwwwvuvuutttttoooonoppqqqrrrrrqstvvvvwwwvvvwwwxwvuuvwwwyxyxywsoopqsssqprrrtuuuuvutssrrrrrrssssoEDi1&3,!)(".!)("- +-!'9,8)',''$, (&!'"( &)#$*&)"("+!'( -#+,&*%*%-!)8+60%-+$- '+$+%,',&3&1vz~~~}{||{|{{zzzyyyxxxxwwwwvvuuutttooonnnnnonnnpoppqprqqrqrrqqqqrqrrqqrqpqrsstuvwxwwwwxxxwvvuwwyxyzz{zzzyyxxwxxxxwxcu4'6* +7)6-$.9-;5+:2&1-"+;.<3(30(5:/>&:,55$+3$(A7KG@Y<.?=3E3%1D=U@5I/$.7+5:/?9*64+8;/=7)4.!)&4'12$18+72&3,%G=T~~~}||||{zz{zzzyyxxxxwwwwwwvvvuvuuttoonoononnnnnoooppopqppppppopooopooqqrrrstustuuuusttvvvwwwvwwwwxxyzyyyyyzzyzzzyz{D5N3#1>/C3%18)56+;8-;3%2/ (H2?7'.G6BHE^E;SH=U2)5>2A?5H>1D@7G=3D=.<@2B7)2@2@B3D5)48+58*7A4E9,:8*5:.:;/=>/><.>.<@1@A5E:-7=/>4&1?1?6(1B3BC2A7(2;/:9+7;,8<,8=,9<,9A5H{uelN\yk~~~~~}|||||||||||||{{zzyyyyxxxxxxxxxwwwwwvwvuuuvuuvvvwwllnnnnmllmlmmllllmmlmmlmnmmnnnppsx{urmonmnnmnnnmnooonopoppqrssstusuutvvvwwwwwwq}A2H:,;:-87(3=/;5)3<-:9+75(3&"$%,%48-<3$/8)47*53'16)43&03%18(66(17)55'33&0;.<7)33%.PNjA9MF>R#/#+;,8:,89+8:,9<-88,6=.:<.:dazjjNWnR_u`v~~~~}}}|{{||{|{{{{{z{zzzzzxxyyyyyxwxxwwwwwvv~vwv~uvuuvvvwwwxjq_mklllllmmnmllmnmmllmllkkkknnmmnmmy|}~}unnnnoomnnonmnmmmmmmmmnoopopqqqrsssttttttY\8+7/!+- (5'2-!*."+-*B3D<.<'#=2G?/>>3I:*67(27)67(53$-0#-1$/2'13&/5)68+8>/=;-;5&/8*6C0=SIbb[}<-7E5D(#!$ -&"!)%I>T}nnQ\rU`x`w~~~~}}|{|{{{{|{{{|{{{zzzzzzyyxxxxxyxyxwxwwwvwvuvvuvvvvvvw|ocJ[`FShhgghhhhiiihhhiighiiiiiiiijjjjjjjnw~xwsykkkllkkkllllllllkjkjjkkkjkklmmlmlnmnnoi<4M($$#!%''!/"& ?1@('2%0:-;E9QE9Q;/@2#-(!&. %=2?SPq[Y}[Z}VTvNJgC=S=5E9-;3%/6*4:,9=,=WKe, '=.;,&!$(!*%f[zzfnQ[qS]tXfwe{nxiyiueuevdta}sb}wfvfudr`z|s~}||{|{|{{{{z{zymwlym{p{}s~txyyyxxxxxyxzzwxxwwwwxwvvt|otwwxvup}mgO`eKWeeeeffggfghhgfgggihihhiiiiijjlpkkmzu{q~r}p}pwkkkkkmlklllmmlmmmommmnnmjqknnl~mnmon~optOR}.$2)$2&5, )80I/'99,86)57+70",>.>1$24,A/%5!>,1U-0A,/@+,;04FMPs\_onsfqa|ufu`w}wl\uq`}lZwvpvmfVom]|p`{hXncOcdZyfZymdiYsi\~skbZ|_Lbh`lggXvYF`WEZ_K_cOceRij\woafQbkVhiTfo[oeObs\lq[ln[qr_~nWlmVfkRc_F[eSmgSkfRcgRbbO`;,83%.3%.:*4*'+3'(* '8,7<.;# B17mTbr[nqZnjO^iNZgLUeHQhKUjNZnTbnTbjO\tZiqWfZ>DY=ChPYqZhwarpWglQ]rXf`IS%9,7:,74'0'!+"2#'+$#2$*:*2N;HjQ_^DKlQ\pVcmQ[lQ[t[hjP]rWfrWcgKTfJRiMVoUahMXfOZgOYfOZbIT\ANZ@IZBKV?L\DPR;IL6DQ:BQ9BN8?\KXK7AU?KS=IT?N^M_L=FbJSY?CZ@HZAK`EQlSdnT_WBOK6DO:HN8DQ>LI5DQ;HaHSiO]H3=B,5>*2H8DG7CH7CXAKSM;7I/0?&(/$")#!)#")$%/+-:#"*%!(&%.''/K:F_K\TAT`MaP:KI7HC0=UGc>/AA/@M9LO)2@*1D-4?).D.7@.8;)4I6DN8FP;IP;KK7GNnZlfRbo[ms]niTdeQ_bLXaFQbHUeMZbKXaIWiN_dKXX@FT=EM6:]DKkR_cM[\TjeO^i[tWnTUm!6(3D5C2&,*!'."(, &%0!(;+9eM^_DM_FP_DM_EQ_ENdKUbHUaGS]CMZAKT=DG58`KU^FP]ER^LZ`P]ZFS_N`VBTS@QYFUYCO`M^WCQP6AG/6ZHVWDTQ=GU>IUCT6-8 &!!(73>,(2<1=M9FR;ERGO>NI8HD0?,2>)2N8@SL8BH4=J7AJ7BM9FS>KVAOS?OP;KR=KK5AQ=I:/<1*7+&2$!+&$)8/=WHXZIZZHYYGXYG[VCUWDRWCPTCS;AT;?S7K8EI:FI7DF2=D2>J:IO>LM9I>:K=:H?:H94B&",$&;.;[GXSMTEXeUldQdcIUjP]tXfmR`[BPP9EN9DO9CP:CO9CN7AK4=O:GL8CL7CO:EM5@N8AN9CPKR>JT?J=0<# A3A!'-!&, (+%O=I8)3=2?4.9/-://;.,71-8=6D60<($-'%-# ''"*,'-+&*,%+0).-)/&!& "$"!)'&...9/2>-5A,/;-.;'(1=5BJ9ETER,(0 % <18B7BKBQ4,;'","$9-9=2@J=MM;IJ:HH=ORJ`ODXD3;E5@7/;*)/"$, %3$3+++%&  #$.&0B4EE6FE9H$,:'0B'4E(2C!%.%#'0 $."%.*)33*5&%%%!#""!"#! "#$"!($#* %)$.6-P>5B(%**&.)&,(%*&#)$&"##')&01-6>085%,3%,4(1@2?D5CD4DC3DK9GP>ME:G44@.06K6(14$// (6(21#,+%'!9-85)3!0(+;279.5L8EO8B>06J6AVAOH8JI4A<1?H=OPDYYJ^UJ\;5B#(%4 /+('$#%   "$(/&4;1@%.&/#*4 &/ &/ '3#)7 &0"&/#(2'&/#!!!! ! !" %%&-$&- $&#),(2@7D*!+*!+<0<80<.*3*'-'$(" ## "$!#)#($""!%!&*$+C4>F4@>4B51?/,90*7:.;=0A;/=D4@?2;809,'-*'.(&2%$1%!, # !!#!"('/44@46B24D,.851@3'3/$*+%*&,!), '"#9.:#$ ?9C8294',8/:1%+, /$)50?74G<9M=5E:1;907K>KWEVR?NK7ES@NSBQR>LN;GM;IVEVQCT>6B:5B>9H?=K509.##,#(8+7!,"''"("*$(#+%($ ,'&#(+$*,$*'!'! # '"*$,$ +  ! ! #"& #53<('-! !# ""$!% !!"%$.,,:43C@:LI>NE?NB=K54B"$-"."1)&&%%$# "" $&)!&""" %$'$*$ ' ""  !##*"",%#,#!'($)$#$".$1*)3*&,$"&"" # % "'"$#!%%&#)85C65H+0@*,;)&3)'0*%+,&,*&--(0-'0-&-,&+% '"*&# $ #! /0900=-,8&%./*4.&00%* .!*"&,%3'/1%/ ,(.2/6-&**$'1-51191/70-521>3/<.'-/(,2*/3*.Q>IqWafLVP;C[GSbLZeRZW@JQ20<22>13>36B/1;1/:,!(9*4* %#'#,")$"""!%&&    # "! !"&$%1&'3+.?*0A#(7$&/!#,%)!.)'$$!  "#&#% ! $*  !!  ! !! )% &$$"("#$!-*-D%):"$! ! $!'!%'%.&-="(6 $2!%2$'5%",&$.'"*( ()$,)&0)%.*$.+&.%"* '##%!" "" ))3&'3 + )%!#$ *$-!'&';,7C4C$*$*+&0)$++'.--5,.6,.8,*7)&-(!$+"%.%*2'-@3=[K^P@JC6:LAHG=FK@JK@GKBGG?DB69^N`A6A1,7+)0+*1((1(+3$"#$ ;.93'0% #!    "# *!)"+ (7!,$3 $.&' +*'%(('$ "$&"$!#! "#$+%&/ $$" ,!( &#$4!%5 "/"%3"&5 .#"+  "#!$&*7"+%$/"", )%&0%!+% ('#,'#+&'1(*6''3'&1%%0 ) %#&  %#% ( *# &""'!&;-76(4,*2**5*)4)'1('0)(0$"($%$ &"*!#9,5H9JREW<17835>>C=>C@?G??G?>E>?D@@F6./TGZI=M.)1!!!$$+$"(&!%#!!+'!#)*' ("*'&!,",#*" !   !! $ 2!"3&-A#*=#"6! -! /%'9#'8$2#/!$2$/'' "&- "*""$$"")%#)&#)'%.&'1%&0"#- )!#- !+&$ !"$")&'!6'1)%#!%!$! ! # /')1&&D7ASFZE9C@<@>=C?KL@N1)1%#( $0',#0'!*( !#'&$(%(#+$!"(&.$ #$6 +"!"#!$!(!&7 (9!2$%:#$4"&6 &5$0#. #/""1-+!)!#($  ! "$ %%#+$&/%$$ $%%&""!$#"& $! %#3%.6)3""%# ( '4(1I;GRAP=/4*"!610>8:A;>A:=@9;A:>A=@@>@?:>@:>,#%G=FUFWI;I"$=3=%!#*!'!$,!$,$*"&"$! "!*"+%.$$ !".$7&;%8 )? # !#!"(#1!%5%&* -!!.+ "0##2%$7#"5$$4 ,!*$!!! $!""%&/%(4!* ' ("/ '8!)<"&9!%2 &  #%)$$(!!!! !"%""" &-!)% *%! .'0*!)6*6F8IK?P6.3&# /0/4893983:95;;:@B;@F49:177#76;K@RJ>T*#,?6F0(1  ! "!!  !%+ "& ""## %!!!" "&!"  ""!!"  %!( $#, &5$5$6"3 0!"&""%%&+&$+#")%&1 $.#-!' !'#$') -$&2#&4 "0!"/&&!$ % #("#!#'!"'!# !""##&"%)%!(1".@&8V#4S!2P!0K .G ,E#+C $/!"%!!# !"$!'!$(%) $@6D)"-!' *!)>4C,$+!8,5A4C>/B.&("-.-4897=;286389?9=?68;!236;.7A3C/'0%%C9JD8I-%/$#  RENXGQ"  #" !# + '"$0!%0   !")%,%-  !.#1!/ .*$"!! $#$("#%!#!#"%'"$' #'#%+"#* "&!"'#%,%(0$(0"&0$(/!&,$)/$&-!##'#(-!'-%* "&  ! #!!)#)@)>(>'>';$7&9%7"2(04*6+%,*6."(3'0* $$7)40#+1$)7,1<0;A2A8,3*!#/')302123334223757QBNS@PA:D246545512404(!#4-19+4%0$+:-7?2>=2@-$0!,%-D8DeTehQ^iQ`kWgM?O;0=&,%.$' #1", )?*@( ##!  " %!+$      &-)(# "!!$ " #!"#!! "&!" # !$#"& $(#&!#'""'&*2#&-!&!% #-!+B*C$7 /* - 1"14-6?4@-"-5E/"&5)0)$<+5A0;<,5<+2<.3;.8C2?F6AM;HO>KTDRVFUWFURARXFTWDTWETUEUWFVXFWM;GVFXVGUJ:G?1;7)1C2=M;KF5B2'/' # '+"'$)# %!@4@6,670;5+69.<1'28,93)2*.$$!.( ++D(?) $" &"!(# ("!- /(#!  "! "!$!# " ! !!!$!% %!%! % #!%8$6#4 0&."0.* 4)/'<8>X7(4:+8=0<<.8;*6G4A9)/4#'8-/G]WF:@J8EO>LQ@NPAOOAON?NK?Guo=E3BM=LM>MN?LN?MPANC1F>,5;-79*2;.XjThdPd^O]=/<@/8=+2=,4@-5;)0>-6D4>B3>5'2A2=K9FC3.7:(2dOcfPbQ>L)N>KB2B4'.F6F/6X)Fx-G{/Ev32L/!&&&$(+$/+$1&)'!* ")&*"-5)0 %,.#"$$& -!#' #'$*&) %&$$" !!+!& (")1%."        "&.$)0',)!% !*!$* -#&1*1&.#* %"(&/'1#$,# %) $!.$,5,2/&+7-2:,59)0A04C2:<,0@06*, %#1#)'#* '0$*XCE+',10:-'08)4@0;B3@?3B+(:-J*G!5( .<)3M5G9>^RH_T;DH8@G4@N=HdPb^J[^K[?-6C19F3=H5=M9DK7BL9CE9J@9KR=GjPYoT\pT^bHRM8CM:AK:CK8BK7AI8C7'.8'+F49I5>YDS\GXZFSO;FI27N9D<*0D/6$$7+B,G$<52J4'3 "('&$'%,#)#*-7$*$'!&%'+"## %1%)5&!%'%." $"(1!$#"! " -'>!* #*)%.0+6##-#   !&1%2%#,  !)!#/$%4 , (   + +    +  <,05'/! "  "H59K39E/3H5;@(/H;F19I.5E$  %&1%+<:Of6FZA('T-+8$&6),S7;K7?7'+VFOPSg2$6) ") % #*)'(*&&1#'9*3."+.$,+!&) #1$)H48& $!%!("*&)%+(/"+- *0"++ &7)/9'.=,927RCA\ZDU[GUZGUH7A.!&4%.O=JP>JSAMXDRL9CR?IR+3-#/#,%!'!*$.!'(")$,#( %% % %!'")  )#'."%2(-4*520>,1A%8P$9Q#4F*2@#+2&+'.5(.81.64*03%)#5!!&"!%*")"% !!##(    + + + + + +    W=HN6F6-7%!!#!* $$"#%]Id;)=$#$"")!-9,8$  %"0$4G+/:D3?OM7>M9CG5FPNJ?NLBQJESIQZLKZK?NI:*5-"*6,4@:B@4?9,4+ %& .$,)#+'& 2$+( "*$/#))#'0#+8,6C2>L:E\HXU@OZFUU@ORJ4>K5?M6?U=IL5:M7=M6>M7@O;KB/:N9DS>J7&/SAR`M_^K^Q?MN +% ")   + =6C:3> '$%3A"'0+2(+@ +@ ,!2I$!&9':(;,@0D"!(&-!!#    #" '#&%+%&*180:7+3F5@I9EG7BJ;EF=F?:BJ?MF7DXDPS@NH8EH8DH8GE8F7,31&.8.8:0;<0;C3??/93&.=/7F9AB5?=/61&,"!,")+ %.!')#:,7.#*(#7+55)11#*3'.=0L5>N7@Q:CT>HS>Iyd{zf{VALN8AG5EG2;P9DT?L, %eRd_L_^K\L;JF7F5)12&1+ '%+#&- $/"',%(!#)'#( +$5'27*54,4   + !!""&!0+7".?$/ &",   $! &"& #!%!% !!$#  "# +  + icyWL\$,$+#*!%!&"4!2'; +B,B,B/C!0E*;#3"2!."-?'6#,!    ('+ &! %!(/)10$*3%,4&-4'-1%+2'-9,54&.L8BE3<8(/F5BL;IE5B3&.9+4=/:B3?F6CN/9E6CJ:GQ?M_L]UBS[GYXDSVDQT@LW@XJ7NR:DQ9CT[BLTQ;FWAO$aN`aM`VCSJ9IM=O?18C4>?1::-24%,*"2")9*04&,0#()"*#' ' %+ +!,%' & +    + -!(1(2!$."*"  ""#-)../(%'!M9AXBLZBQ:+4>.7>,5C48H7>A/2D29D49I7==+-J6=1+3    84@i`oaU`/(-&  $$F?QYH[.0D"3$4%3'4(7&4+"1$2!+")"'   $,*.>71E5*8'#%.*3A5?;-8<-87)2;,62$)7(04&-;,4>/6@0:F5AM;IE3?8)35(1=.9A1=F4AM:GK:E:,4=.76(-&-%2$.9)1-!'.!)7)4.$1C4A?1=I1>>.7UBSRAOT@PZGYWDTU@NWAPT?KR>PI8QH3T>JVBO)bObaN`YFWN=KG7E2%.2$.7(15&/;+74',<,6E4?C2=?/75'-7)05&//#,+!)0%-2%//$.,#+      "4*2'+;"'3 ("$ !&819+)48,42%.B2:gMXfLXWBNW@KVALVBKZEQT?FXEP@.5N>B*$51H7*<;.>+ , #%,#(!&$061?!$5)*"/'->!%2*&'#"     '%0'$.!#+#'1%)2G;DQ?IQ>HI8ATANE4=6&0?.6:*5F6BB2<9)08*0<+3?.7@/7>.6>.5?.63&+<-37(/<,4M=HcP_eP`dO_aK\XES?0=B1?>1?M>J0$+9*4K;G^J^YDVP>MbOaVCRU?MYDQRGO=Q?.9H4=TAMVBO3$.cOb`L__L]YFWUCS[IYaM]bN_^K[S@N3$,C3;E4>C2>H6@C1;C3=@0:;+59)48*57(25&/1$($#   + +  !4(/!&0*8#, "  + +& &+*9)"(##" %!&$$+7/7"$#$ 106Q=JT*2H6@G6?QJ7=G59*0I8@K9BM8AVAM`LY`LZaLZYEQZEOO;DJ9DH:H;/;:-6H7DI6B_L_YEW[HWWDRWCQ[GUVAON>S9((G16A.HQ:C_EPnS[U>IC.97%*$&2>+3F6NB/8K6@S?KQ?PE4HaL^`L]\I[WDVQ?PcN_dM^gQaaL[S?J1!&B06H3;H4;J6=M8AM8AO:BQ;DP292*1!1'+7*/M;D@5@M@KC;CC7AK=EQ?IO@L?0<61>?7A >-67%*P:BO:@:(,:)-0#$8'+*E18M9AR>HI16L7@!#"D8F{f|N5?aJTu^j8.6.2:!-2#"$%4!!&//6)"& %$$!! '         N^IW^JV`IVZBLsTfX@N_FO^GS`JT]FO`IU_HT[ER^JVWCOF6=_JXS?.;RANXFVSBRV@N^L^XEUVCPWCP_JZWCOH=fo]|R<_&dJ;pA,EeDMV6FiSiP=^%EoXkI?e63[D3DG2:R=HK8AN?e;;aL[^K]_K^YEXP=O_L[bM\cO^bLZJ9C_JV,0!%2$'5%*8(,:(,=*0@-3A.5A06?/4H6=?,;D2BB59 5).ZDRJ6@7,2K:EZDO^GT--9C;GM>IZDPI8@A09I8AT@LT?KS>GE5<7)1,"(5(.3$*;)2K;I6&/?/3F5;! (!?-2J48H38G19A,2E19."3!')=+1N7BT1=?.7>,4A.6;+2:*1B07S?H4%+J5;8(.:*0A/7C3;=-5>.6;*24&+3'&8*/7)-9+1A1:O=KL:DMLTAPaO]ZER[FTO?LC=Q==Z%#?WNf!/l50k! QUF\?:P03K;2E?3>F5>K7@K6@WBNG5?T@RH5GaNa^K]^K]XFWP>NM;IPO4%aVAT#$##-",7+81"+,#& $(')", $$$1#(1$*1$*0"&0$,#(#,2$(/!&,#( ' ''$) #-!#oT\hMR[DKK5;M9=G490()8+.D:C %""e# 4#,E.6F04`FM;.<2/BD;L{f}~fyXAP9%0L7Ahv~drlP[3"+.(/B=D'*-!!!$  #&9:M1.:97B*(@18/.7F;@0-7(&,'"%5+0.&( +  8      + + + +  ,)6L>J7)1<1>H;F0#*8*04(-- $/"'- &7*0?2:F9BE8BD6?3(.&"5+3N@OE8CTFSF8B@0;;+3E7CE5=C2;&LKT>K<(2K7KJ8BA8PF3-8;,5E4?E4>R@L2$,( ' /#/3)57+68,67+50&.)'#.$.',%-.$+2'-)#& #1%+,!(.#+-#*%!(&7,88+6/#+* $# !$ '!"$"A059(-?.2[EMnMPfl^FH2%(,!%#'(!!>6C7/6 ."K7=O;@K7;=-1<,2,!&10>62A4.;4-5'&43)63,9?.3+$/8*0*"*'$(! ##% !(1-9YFUoWibVjU]~V`"!.('7##(!%#- !+!   #!$!%!7-5,#)-"(""$"6*40"(+%,$, &)#(#)%(&.!*8*3-(- ', %*%&!("5&.1$-0");+3:*2*". %8)1<,5D4?TBQ[IY[HY[HZ[GXQ?O[GWcPa`M^fRfeSf^K\cRc\J]eSeU6C[HaUBQ]J\WDScP_ZFTaM]XDQ_KXV@NZDTV@PWCSD2:P=K^IZVDTL;HL5FL.66&,C2=A0:D3?079*17(05',9*19*1L;FTCOXEU[HYbNb`K]dQcgVjjXliVkgSgeRffRecQbaO`dPaR?K_JYYDTYDT[GV\FW^IX^JZ_K[`K]aL\cN^aN_aM^ZFVS@OXEWZEVO/<=.:;*6:*59*5:+49+49*4;-7<.:<-;6(4C1@E3AH7GI7GA1TCQ[IZWDUXCTO=JL9F#"& !"!&6.=""')"(9-;8,;UMcID]1/E"  +   :*3-)9; ,&>BTW=OiB>O1,82!(3#*2#(- #) +!* 2"(/!&*"- %+#+!$,#,$&-!%%#0#(1#$#(*4#'2!19)69(1>,5A0NP;JWAR[FV\GW]HY]IZ`L^_K]_L\_K[_K\`L]\IXR?LZFU\ET[ESVCPR>KR?KQ=JS?KV@NYCRVBN3%*TCOS@KSBNS@MR@K`M[`N\aN[bM^`L]^QEYGMP=II8CH6BE3?C1;A/8C1=B1/=E1CA/?C1CE2FE2FE0?D2AE3@G5ANFQ;DR=GH6@L:IG4EXEYR?RUBUUATUAVUAWTAUQ>SOLS@NTARYGYWDW_La]K__N`aNbeSieSi`Ob_M`YGX[HXR@O?.:P=J?.JOKU?LZESR=JG6@RANR@NS@NM9EL:FO=LOJT?MT@MUAOWCQXDUXEWG6E-%5( ,   %#("'/".SP@RN@RO@TQBXP?RR@TSAUC3@I8DNKUCQQ?MH7BUCRVCSXFVYHZ]J]]K^]M`_Ma[HZ[GX[IZ\JZ]J\^K\_K^\J[^K^[HZXEZ\I``J`_J]]IZ]IY^HX\HV]HW[GV[GVXETXDPWBOUAMM:ET?MR>JPC1:E3F6?O@N=.4P?LO=JWDQYDSZFT[GTR=F]GUZGRXDPYDQ]HU^IW_KY_KX_JW[FRXCPWANWBNT@LR=IR=IQ>HM8AL8AVDPZFTXFSZFTQ=GVCPI9AN=GXETXESN:CT@NS?MTAOUBPWDRZGW\GYQ>L2,=!,!+" - ." -''8+8<-:1'3J?QD>MAL2&.7+2@1:T?KZETXERYEQR=EVAKXCMZDQ[FS[GTZGTYFTZFSYFR[GTZEQYFQXERVCOYDPXDPUBOT@LQ>IG41,6-)32-85-8$#$!"! O?MRAPUDV\K]fTglZpm\sm\rjYoWCTiYnkXngTigTjkYoiXon[sdShcOen[so\so\rr_us`vs`xs`ysbxuczvf~tf~vgyhzjwhwhtd|J2>7,9^Odtd~tc~verc~tdsc~ra|q_xo[un\tr`yq`yn_viWnkZpn]tp_wr_yn\thUlkZpjXpl\tn]vpa{rc~m\uhVkVFUk[rk]ul]vq_z[IZZGWm^zocl_yk\uhYpfVmdRgcPdC4>F5AB1=K:K\Ha\I_^J^]I[]K[]IZ[GXWFSXESYDSXETZHWYGWZEUPKS>KQ=IR=JS=IO;FQOhVmiWmhVleTidRfbQdeSgeRheSjgTkgUlhVkhVlhWldRgcRf`Qc_Oc^Pc]Pe\Pc[O_WLZWL[VN]WN^RLYOIUDNF6CMBSKCSEIBEB?H=9AIAKIBMKDNLCOMDNOEQRESTERRDQSDPTDPQALSBQZIX]JZ^JZ`J[_JY\IXZGVWETREV:/92*08/9qgqbgcpE29UDPWDP[GS\GS]GU]IU]IV\IV[ET]IV[HT]IV\FT^HUXCP]GVG?A<10+--$9/-2*&.)$*#+(#2%*.#->3A(!,0%+ODQYN`QER]N^QGTLDWTGSA6AB>Q55B88DHCQE>N;4B3.9($,$#  +    +   IH`?CTAEU@BP::G65?%#)#! + 4*3[H[^K_^L^_NbQ@PB1=YGXK:HG6C_L[cPacQcfRe^J[G6BcPbeRcR?NbM]aM^aM`^L\[HVL;H8+52'09.;?3BM>NYGXaL`bM`_M]^M__N`eSfZM_UJYPGTD>H;8?46:258.37+24'00&//%./#-.!-, +*'%'$'$ )&% % $ $# &"&#&$!((##&&%$&%''%&#"""$&$'#&$&$$$#####$$#$#! !   !"!$"&!%"&#)&+) .-"//"01'35)48,6:07;28=47>AAJF@JVMZ\N]bSgJ>N3+42(04)1B7A?18M9=C26A29R@L^JZ_J\bN^YFTUAO`L\gSeF3?cO_dSafQbgTebO]N>J_M\:95$"(("&&&)* @:8D565.-! !# +"!,$#1*1H@NRKY[M_A5>J*.1/5;:>GHCPUL^MANOIYC>N72?/+6!!)$#%)* +-'*, /.-,**(*75?/.4   + + +  !" 3(1JNhSfeRgfQfgShUBSC2@^J^hTjI8Hye|mZpbPdXJ^DAN?;C.$.3'36-9A4DNAR>CL2PF6FN@O:26))#,-$.*#UHMZLXL?O:2@($/&&'!0!#G@LL?G1%%"!!%/'UMiSMiSNgMK_:>H"#)(*..1HFS\Wj^Xng`waZpQI]F>O=7E0,6(#- %!"'+&17 +!&:,6H9FE5A^J\`K^\I\^I]_J`ePfbOccOecNeaMdbNdcLd`Ka`Ia_IacMgfOieNhaMdP@SSEW@9E98D.5>%16&24.07*%,.&.<4@MDTSL\-8>*8;,9=+9=+8<,7<-4:07<6;C#! ""###$' '$%' !/,,:95@A@GK@EJNTZX]fchrkn{uv}~jbmH;:G:0;<1;<.:;1>@1>?1?A0>?0=ATOc&#,1+4/,4%)&.3-2:03<-3>*0;1/;PCTcRjkXslYtbPi^Jc^Lc^Kc_Ia]H`\H_[G^[F]ZF\\H]^I`_Ja]I^XF\WG[J?K410&( $(A=>E:BFEECN--2*/2*79+9;,<=);>*>@,=@+<>*<=);< 34..001/0/!33"11#//"/0"./%-110<>6C^NfiUplXtiVqdQlgRmfQlfPjdPhbNf_Jb\H^^I`_I`_H__J`bNdbLb^K^VGXNBP>9>&'!"!()"$'-$+&%.+.81:H:CSMX8;C4;FLLcVRpYVv>9K?;QKAVOJeEC]<;K*.6**$#))(.3OHVf\s]Rgh^seYqN?N_Vn_WnRJ_OJ\_JZdOb]J\[H[ZFZZF\`Kb`KcdMefPgfPfeOffOggOifOhdMfcLebKebMfbNgcNieRi\K_ZNb84T?5TA7L:1K:8jXl@6> &%fVlm_yk`{RK[,(.+(+(,*,)/+2/3142324454646677 88767453 65!87 67!56320,17HH?G=05=.6UHTXGX]K\]Oc%#'% ()/FBPABJ".-#13;ESLLfMMhG@SSKhXUsXTrXTtWRrLLe5=J58>)-.!*+39AON\^ShH;HbZqbYpVMb`WnYFZXDX]I^cMdcMeePffPggQghPgfOggOgeNgbLfaLfbLfdOheOhiUnZL`JFVDGS3>E#5946799;#:>8:78897868798:78776754210/,,+**((&'$'#%!%"&#($%"%"%#QI^OBR_Pc_Oa^R_eYZM?9F91H91K;3J:3J;3L;4L;4L:2J:3J:5E50J83I70VFA_KFaKHVA8UA6XB7\H9YF9XHHpb|(#'vh]Re&(*! *'*&+'+',',','-'0,1/2041645355667776757576&<<%:<7775543/!20CBMdRio\{q_}iVqcNh`KdbLf`Kc_I`^I`]G^\F^\E^\F^\F]]G^^H_cMcePedNc]H\dPfcObtaywdxsauk[pfUi4-4 34<89A0793;>2>D445L=5O>6O?8O?6P@8O?7RB=UC>SA>^JJfMMbIGXB=\G@_IA^H>_GAdRYq`w'#& tc{TFU%%(&&#*$*&+'+%,%-&+%*%+'-*1.4131313253444454548655655443412.1.-47YL`l[wo^zp\yhSo^IaaKecMf`Jb_Jb^Ia\G`]F_\F^[E][F^\F^[G\_H_aIa_Ia]G]VBXaOcp^qlXjeRcYHXE8E*!% + "$'),88@=6<+23%477?LMMhZVxXUuWTsXTsWSrVRqSQqLLjFE\5-5106#"*)'59jSjiSimUjlSjiQigOgeKedMfiTohUpl[vaTkbYq6>I47547767!6:687:8:696878786655340.0-..-*)''%(%&"'#(#(%'$%"%!&"'#(#&"$!$'#)$''( 0',kYihTd\JW>14}^QJQB8UF=SDS\LaiWjiVhfSeF2;K=J3.5   5/9CAL/8<,,(49>DTQRmVRpWSqXRrWSrVQqRMl:/?FD`@?W36D*-mTmjTlfPhdMecNegSkcPg]Qg\Xo9;D1:B!5801234657664433445644434332201-/,+''$$ #&"%"#"$ )$($(#&"%!&"&!'#%"$ %!'!&#'' %4)/eVhVFSF8@E;?~znrI9-H:.J>5G;4?1(F7.J;3J;3H93F85>0.D42VDE[INVCJXCKXBBdLNgNPeMMUBCO>@P>Is^r +mZoVDT **%!%!*%+&-(.(,'+&*$,&+&+&*&+(,','.*1/31424255555432224422323210/..0<^JI`KH[GB_IE]FA^F?]IA[GA^KSq\m s^sO@N'01*&,'*$-(,')$,%+#*#+$,&+$+&+&*$*%*&+'-*1/32323333222301/1(:=22445533-,&16QEYdSmn[wm\xn\xjUpeNjN;MiQmeNjbLdaKd`Kd`Jc_Jb_Ia^I`_I`_Ga]F^\F^\F^\F^ZCZXCZRAT]MbhUhbL]^JXXDUK:I4-6" '    !%1.3VL[YL\H=KNCTUI[QG\A6CVPnRMlQMlSMlaTlMGX4=C241032456636#58344433210.0-.,-+,),*+)+)*(*()((&'%($'"%% (#%!"#""!$%' '")"&!&!&"&  1,3dQ`lWgRBM@52]NRugNWeKSkR]cYfRGG]UZI@>_U]QEDI=6OAh`nLAAZNRQCF@32L<:L;6TEApdjvn[j  lXi\IX.15)$+'+&*&*&+$+$*")"*#+$)")!*#)#+&+&+&+'+'-).-00121304031324464535342211.-*).4:PG\cPkm\xcQj N;QbLhdMfeNhdMh`Kc^Ib`Jc_Ja_Jb^H`\F^\F][F]\E][D\ZC\ZD\XC[WBYS>TQ?SWDX^J]eQebM_S?L=-4O@M<2<&!(  )$)E7EA/8H;KOBUVH]]Pf!7844333333100.,)+**()&'$'"$!!  "$!%"# $ "!B><!$&!&!"""##$"# !H>G cQ`oXi_L[C5?9+-xkRDD~QEII=[Kb2&0gVqlZtp]z^L`E0=^IcbLf_Ia`Jc^Ia]I`ZC[QRBBPA>TE?bNMfPRk}dSa%"$p\mVIW:4;("(#($*$*$*%*#)")")$*%+$*$*%+&,'+'-(+&)%(#)%)$*&+'*)*(+)-..,///0-.012100.-,**)()"#*/791>\LcgTniVq4%. + +_NfE7F7*6cMf\G^UBW)0'$_I^_J`^G_]G^]H_^H_^H_]F^^F]]F]]G^\G^[E[U?TS?SXDXiTjt`ur\qp[pmYnfRf[M_NBRF9GH:J0!'  !$!$"# "#""!#$!##""!"!""!"$ #*,,244!"     !"#% [Rg   ("(gUdmYkVCOYP_A5+yrtggNTfMT_ELWKM|UC@`PSVEBZKOXKNs\ctVYqPOyxfw[M[  gTiaQd?6?&!'"'!)$+'-(*#*")!("*%*%*&*%*$*$*%+&)%(#(#("(#(#(#'#'$+(+)+),)-.-///--*+$#"!#" )/31C00A()8C8NTBWcRlI;N!dRo"! K9L5'2MENDKULS{w|wxu`S`TDBRDHcV]UFCQA'#)$+&+(+'*#(!(!(#(")$)%+%*#*$)$(#*$+&(#'"'"($)$($*&*'*')&*')')****++,-/-0+-,,++,1$/7%-7*,<30=WI`L=O9+;lXw6*9K=P;.A  +B2BbKebKcdNfcMebLebJbbKcaKcbKcaKbbJaaIaaIa_H__H__H^`H^P;OQ@ScRglWnqZpoXljTgbK_=*59+85+5 !""   !! "# $#"!!!!   #$+* + 0&,p]n`LY_KX_JYO>I:0+`WhxtjatXKUbXkQCFPA?SC>WFB[IEVD>rep|j~kWjXJW r]nkWi:.8,)*%+&*$*$*%(!'!'"(#)#*$*#&' (")#*$(#&"'#(#)#(#($)%+&*&(%*'*(*()()(,+/016@HU!45--++((&'&+%.*+582>@3E_Me2'33(5^Mg/!1 # +0#-YD[bLf`Jb`Ja`JbaKdaJbbJbaJa`JaaIaaI`aH``G^_F^_G^^G^_G_]G_[F]Q>SQ>TSAWbPfiVk_J];)1TBQTAPG7C5*5    !! !! #"!  !!K?L +kZjo\lbO^;-73+35--yu~wVFKqhO?<^NPWIGUFFVFGTFG^QVyn<.9nYkH>F + + +dRbr]p9-4,*' ("(!)$*#'"( )")$("' &(!*")"(!'!'"'"'"'")%)#(#)$*&*%(#($(#&"%"'$)'%% "&(('+*-,+,+,*,(*$&!#;8EN?S;/=B4D`Oi6(5<,7?+I*)5&0[G`aKcaKd`Jb_I`_Ia_Ia`JabJb`I`_G__G__I_`I``H``G__H_`I`_H_]H^^H_[E]WBZK8NJ:NZMbVFXS?P[GW]HYYAS!      " *!%n^s*"(!"& "^M[`KZ=12I?MzPFRYMWshzWGGYGFP@VI5KLFlXh`P\lWdH8AD:CL@BWJQ|upo|pYIGYIF^OPydomzp}bkR@8pYi1), + L6FUC[]JcdRjfRlfOkhRmo[s^I_]F_cLefOgfPheOgeNfdMedMedMfdNfcKcdKcbLdbJbaH`aH``H^`H`_G]_F^^F]]F\\E\^F^]F^ZDZQ9U<6O:6L94r}|rzoYi& +.9;.6wcu:,2(-0$& %'!( ' ' (!'"%*$+$ $ ("(#'"'!*$)$($)$(!(#'"'#!.-]MQBAB%%!'!&"%"(%&#%"&$&#%"$!%$$"&"(&+*+,*+(.$)))1XKeZHabNjjUriUqiTor\wgQjaJbaKdfPihQkhRlfPiePhfPieOhfNgeLfeLfeLedKccJcbJbbJacJbbIaaH``H`_F^^F^^F]`G__E^^C\               !!   bSe^M]B29>.2>/5M>F\JW>382(#h_rriulsi^Tlvxx\MWeYgK>:WHKI;5M>8O?9R@:rdkjfrh}[QeKCP DH`R=Ho[l:,4)+/%!% '#'!(!(")%("& (#(#" ' ' '!'!("'")%(#&"'$($&#,)+1/#.+&!(#(#'"&"'$&#*+-/*+''''&%&&('()*,+,+,)+'*$*"'+ODYdRpeSohTphTogQmjTonYrhRk]HbfOjhRmkTnjTmhRkfPihQkiQkhPigOifNhdNfcLddKdbJccIccJbbKb`Ia_G_^F^`H`aGa`F`             J:GiTdgQ_^HUbNYVDQ>06.(#6-'~`VsSH`|wYOhtm[Vlzof`~ne{eZhM?Z,4K%>%8T(8S#)6jS`s[j6+2+,/("& '#'$'!(#)$(#%!($,&'"&! !%!%("&!& (!(#&"'#)%%!&!&"&!&#&!%!'!%"%"&")(NJZTBQQ?OVEWVGWXHVVGTVHVXIWUFUSFWSEWTEXWHXZIZcTmtyhSojSogRmeQmlXsnXs_IbdNgfPjhRkkTnkTnhRlkSmkTmiQkhOifNifPifNifMfcKdcJdcJdaKcbJdaHa`H`bHabHa() )) ')!*+")+"*+!)*&&!**#,-"+-#,+   ! !+*-3(//&-iVggRcgRaN=H8*2C:IRObGBLda~c[v_WnXPeXL^e^{[Rc{tOERupwrj_pPB@PBBSSVK==K>9XGHXHJn`qoaroatEBR!+A.;[&0M 5 _L[v`rJG"84Az~qpie}B7C1).9)1-"(:,34*25+16.7:./UK]SOmd^{[NUG96QFGSPVF98O@Ar^op\osawiWkPAR++G .L)F(B1;6HRBQ]K[`M__K\]L\WGWXKYZM\ZM\\L[^N]]M]_Pb`Rc`Ra^P`]O_M@P:1=I@O]Qc`Rd^QcbTfdUh`SfaSdaSecVgeYjfYkhYmi\nfYmi[nk[ni]pl_rl_rg[oj\oi[npbv}jxe|xd~ze}h{gp_weWnVJ[]Nal[qxe}~i{guazjZsfYvzuXE^bNhdQmdPleQmkVqgSmYD]_IccLgeNiiRljRlhPjhPjiRljQlgOhfNhgOigOihNigOhfLedJdcIdcJddJe(#/)#/("/&"/+$2,#2PEXzis_tr\p\J\L?O%(+       !fUiuc{RBR<.76)-<-2N;EcQ`E7>.&%0-1UKd=0*9)0=)2. &2&,"B12*^Tg#%b`^U_J<6I<7K=9I:6gS_q[mq^r`RaI;H )".!+H/M*G)C2+<)/0G0)93+81)5/%2,#/+$1+&3-'5.)5.(5+%1,(5*&5+$2,#0*"/)".-&3.'4-%5/'5/(6.'5.'50)72+:/*80(61)70)70*81)80(52*83);5,;5-<7/?5,>7.@8/@:0@90A:0B:/AWG]kk}js`xOARE8Fzjyd~kj~hr`yk]w_Qo|u\I`aLgfOjeOkeOkgSop\v`JcYE\^H`_IbcLegQifOheMgdNgeNgdNhcLeeMffMffLfdKfeKecJdbHabIbI;HKA?3/B23:,,E550$!=,-.%#B234&&@/18)"ZRfMF]  |mnid{M?:OA=XHJiTas^qq]qcQdK>NF8F6+4B4=%)A .1%?@3D+3M@@WC7F>4AHKK=KJ=KG9FD6C5+5B8DB7CD7DB6B@5BA5CA4C=2A?4B@5DK=IG:GB6D?3??2?E8FC7FC8GB7FF:IH;IK?NPCSPBROBSL?OM@QL@P>4?ODSKAQMASOBSQDVZJ]n[rr_wsawubyvb{s`yvb{q]tr^swbywbzs_wgVnhZqeXqrq\HabLgeOkfQleQlgRnn[ufRkYD[V@X[E\]G_bKddMgbKd_IbaJdaJdaHbaHbaHbbHbaIbaIc`G`_F_XHUYGV=/9B1:?.8bShq\ut_wjUikVjQDSNBQ82;      !" +  +/'.o[nmYjeQ^nWd\JV6+-?9Ekj:0,~xeuK@O(3',+!2&*), #+,##7*)B219'(B.+VNd!~72AyvbnmYfs^qt`slXkWEWD5GL?OJ;G4&-9*2-&'%)=_M_@4E)/H7=W)#-'!))#,)#*+$++$+4*2I;IG:HD9FUFWM?M8,6' '%&' )' )&('!*,#-Y@KZBJJ;IL;IK;II:H2(2.&-2'1;-;B3BB4?I8CI8EJ9GJ9GM>LMAPB6BWGUSCQL=KN>LP@LJ9FI:GO=LQ>LRAPYGV^L]aO`N=KKL + +hWhdRblYhYHS6)-HAKvroe~^?E^CHI4<=0)=*2;,72$+.!':**0#"D2-H31=++KBVOFZqmeb1(7j]usYht_qq]qgUgSBU?2B?2CQBQSDL;/3V@JYBLC;G%&+,/2?05F=N@=Q~fdXRm@9JG?V|~syiJ8C TDS\K[VEXD7HB6HL?RVGXQAPD6=WFQYHU9,8A7F+ +&##0B7E!1175H<8HQG[{i|z|k~k{h~kzgtbyvcyubyo]tkYpp_vud|vd|xe|vdyvczwe}vc{r`vvdzve{wf|ve{xf}yhvf}wf~wg~wg~wf~yfygxe~yhziygyhwffYnKDQA('S9M>6GD:IA7GA9KB7IA6G@4D?4B6-:xf~mYkO>LO>LR?LR@MP=KP=KK;FN>JQ@LM=JO=JO=JN=JP>KNS\M]eUcaTa^O_]K\fWm@;2BF9GJ=Jo^s`ShSHYYK\eXhgZlgYkfXj_RdXK]WK^TI^>=Q+,>''9('8$$3$$262CUK^XL\WK]`UgcWlgYndXmbWj`TfYL_we}s_rRCPTEROAPM@NSETK?JI=GI=HOANL@LNBPMANL?NL?MJ>KL@MJ?KIJRERB3;UDTVCTTBPTAPXEVWFXZGYZGZZFYWEXWDWMCYHFdh_}zms{leTqhVthSplWtgTqfRomZwua|iUm[F^[F]_HabJdbKfbLgcLfbLfcLfeNg\JYC7C^L^t`vp\qYHWK:F\K[\L\MAP@7G<3A + +?3AUE\cRip_ytbo]v  +paxn^rlYmfQbUAMJ9D4'/=1zthMME8E:/=6-;2+7D8GK=KRBOR@MG5AK:EkXnXJ^5*30$,D>JICPG@OHBQHCQLGVKETEBRA@W02D./C--A)*=++=3/@IBSUHWKCSICSIBTIBSJBQOGTI@KfZmm`xcQa""'% .22!     !  " ##$#%    !$F9EP>MUCRUDSWDUXEWXEWWEXXEXVEWSCUJ>SCB]EA\]TouirqhYtQ?[aMjiUsgTpdQn_LhkVqq]vcNf^G`bKebLfbLecLfcLfcMfeOhhTifSek\nu`raO`aN_]IZZFUS?MWFUYHZSCR5,8.&4/&32(57-:C7G#'/)8qd~p|y{mM:=F65L=?;,-H79<.0<.-B039*)G88,F23@+)T76G7A?)(E:JGNE6C<.;8*72'40'51)66,:7-<91>?5BF;IG:E&$UEQO?KJ8CI8BG5>`M^gUi\Nc>1=;0:8:I6O>R//@+,<));((9+);1/A98J:;M>CUAFZCEY>CTCU9>Otipc|lXk"#!!"!"""$#!"& % % &)#%#"&!$$%%#""! +   + &),E8DO>MR@PTARWDVWDWWCVVCWSATP>P?1B81D@=VD?W]Ql|mx|r`Li\FdgQogSp\HeSB]dRnr^{pYt^HabLedMfeLfhOigPjfOiRBRUCTTAQUBPXES^JZbNaB1>cP`XFUP@LH7A&N?L@3?5*6<2>7-:5/<,&2)$1 $(.$/7*9F9L}rvbQfB5FRIT!!!&5%$E0/7"!Q65GOI=8G;=NDI_AG]GJ`]Zs]XnPLbJHZ00PF7G5*6:2DF@WKD[YQjna|rzx^LhXGccOmhTqcPlVDbaNjq\xt^zcMgbJceLedLefNggOiSAQXET_L[bN_iThq\p\I\[IZgSeiUhdRfE2<+=/:B4?+!)?1;Me\x{mKAT=4FD9KdU]?11#$ # + %((3"!A+-J0.D//G>O;.4G=NJ3A@4BC6DF8F@3>JNQ?PQ@QTASSARTBSR@RL2>J=IA5AE@PGEX32BzmH7CK:GH7BE3==-7J;I_[pb\spf}|nl`t[PcTJ\NEWOEXODUPFWWK\]OaiXkuextg~|swkqbx^M^"")"*,#..$.2&02'04'/4(33(41&13(45*76*77+86,:6-;6-99-:8,:7+97,:7,87-89.96+6J=KqoocYk(%&"% %$$ $#"#! "$"6.6J;IN6JLE^PIcPE_aTmpazovoWE_ZFbiTplWsePkaKhfQmq\yr]wjUm`G`dLeqa|ud~r_wL?QH9HN=KP?NUBQUBQP@MJ9HH8IRDV\L`cSfYK\VEYhWjeRgjXlOAP-"-8/@5F>2C9.?wSDR?.):*+"1$ '"(. %;*),B++6)2E,-<.9D:M<2D^Mazf|zhJ:HOAO,$,#%%&("*H;FbQaiWigSdq]n}gzn\n1.9!!+ "+&!+ !)2.793;;3=<3=6/9!&3/=zs2+9I:H9-:C3A?0=6*5:/;6-:3,8:3@7/>90@;4C<4D>5D;4B<3B;2B92A92?70=;3B7/=6,:;2@>4B@4CA6EA5DB7H>5E?7HC9H<1=@4@C7DF;ILBOOCQJ@MJ?LJ?KMAMQGSRGTRHVTJWWJZTHVSHWSHWVK\TIYTGXRFVPDSPESI>J<4?ve|qrt??J$ % %$$""#"""##"!F9HL=KL=LN=MO=NR@QSAQWEVUCTM=K@2?2'2=5GLE\ME^OF^SIbcVpueprjXs`JfhRmmWsiSoaMjePllXus_{s^zdOh`TjTDVZGYTBRI8FD3AC4?E4AE5BC5BH9IG9IK=OOARP@PH9IN3BA4Czgzu`pm|i{]K[PAMP>DJ6?@17A28<,0@056&-<).>.27')G49D14L8:SBMW>CTANQAQQBRlZnqzsRAP:.85+3!  ?3=UCOTANXCOXFPN>HK=F !'%-43=74@PJ[SPc-.:!*!)&(1A=Licw~yz+*6OAQ5*7=1?>2?8,84,8 )'#!+'! -$"1$"/"!-!!-"!/*''))&($#0%%1&'3$$2%%1%&2$$3#$2#"-)#**$--)2/,430751:2.60,4/)05.6:3=71;84=:6@<6A?9C?8A@8D?9EC8A4-5607m^tmqs|l!*.#&$ "$% $ $""!!  &*-I:HI9IJ:JL;JM;KO=NQ?OP?NO=MI9F;-:0&1@8KNF_UMgTKdTKd_Skm_w}lqta}ZHdcOjlVrkVrgRneNkhRopZwu_{hXpdRjl]wl]vj[un_xk]xn_|m_|m`{m`{VI]o_{jYqhXohYpgYrj\ti[riYqqf|t{qg|{qc~{x{~}?4=o\t]PdUK]UHYTGXMAOOBO^L^aPabQbaPa^N]RDSXJ[rf{ykyip`vdSezh~dUgMDSLBS_Sfrdxwg}wf}wf~sbv<3?QBP5)6:.=5+8;/<8-:   !%'* **++*"*#'0(+5*.:,2>.6@3:C3;E3:E5:F7K8>K5;E6I8=I8=J5MN9.7+$+4+42)09/9E8DF8DG8EH8FE7CC5BA6A1*290:I:GL=KN@MN?MF9GK:KI9HE5DC5A7-51&.:/5D4:VBIWBI`HQ[EK`IPfNVZDJWBFA27S>FL:C9-2p_rtsoyiyl^Sd>6AXK\n`sl^ueYnbWmi^wl`xj]vaVmOH[VM`;1;LEUVN`YN_PHUPFWNEYYRh[UlZTjGBQ-,3RBQ=0>E8G?2A?3@) ( +       +              #!)$)2).8-3?.7B/9E19G2;H2;H5=K7?M6>L6>L7AN8CQ8AQ8@O9BP;CQ:CQ8CP7AO8BP8CQ7CS2>M'2=WTfg[rtcyygqqBCP$!$%## " ! ! !"  !5,7I9JL;JKLN=IP?LMMO>NQ@QS@RVCUVDVWCVXFYZGYXEWWDUVCTXFWXFXWEWYFYYGYZHYWFXZHYZGY[GZWEVZGYZHY[H[[J]]J\]I\\I[]K\]J\]K]]K^^L^`M_^K^_K_hTenWifyvtyetetgvsZipWgy^n{`oz`psZkjSefO_aL\aK\aL\_KY^JX`L[`KZ_JX]HW[GVZFTYESXESVCRSAOP?LL:GC6A 322YMT#"  &H@QF5B9*6:+6:+6?.:J8DF4OJ:HL;IJ9GI7GD4D7+8.%1IATPI_WMh\SlVKeJ?XgZuqa}|jstvceOkkUpoXtLNO>MO>MTARSARVDUXEVYFWZFXWCUYFYYFXXDVXEWYFYXFYZGYZHYYGX]J]]I[ZGXWDWZGY\I[\IZ[HZ[HZ\J[]J\]J\\J\ZHZTCTRBSSCUYFW\JZ\I[^J\_K\^K[[IZ[HZaM]|csx_qoVhbJ\oWieP`\JY_JZ[EVdN_jSdfPafPbbM^^JZ]IZjTfpYk^JY]IW`K[]IX^JY\HV[GTYFTWDRTAOT@NO=IK9F0-0         5(23'05(2<,88*45(3Y?IW@G        +! DDN{wyZM[qbswq:ARslaTjr_vwe~qt57>"% $& %# # # ##"!#"$#';/MSARR@QRAQVDUXFXWEVYFWYEWVDVWDW[I[ZFYZFYZFXZG[\H][I]XFXYFYYGYYFYWDVZGZZIZ\H[[GY[GZ[I[\I\]J\UCUM=MA4E@3BA3CF7GO>NYGY\I\\H[[HZ[IZ\J[]J\]J[[GYZGXXEV\HZ]I[[HY[HX]HY]HY\HY_L]_L\^J[\HY[HXZGW_J\`K\[HUYGUZFU[HV[FVWCSWCRVBPUBPR?LQ?LO1>oTaYCN   + 38B{|}q}|urkXf]KYoAFVQWik`wsax{hprpe{%$""! !"# ! #""##!.(0A3DF7GF7FE4EG6GI8HI7GI8GH9GG7F@1>4(26-;NF\NH^ME[UJd_Tm_Rl_Smk]wtd}{jrr~jM;IP>NTAST@SS@RUBU[H[]J\\H[\I\[H\ZGZ[G[[I\YF[[H\\I]^J_YGZXFXWEXVDWVDWZGZYGZ\I\ZG[ZGZYH[ZJ[ZH[ZI\TEWG:J@2BC5EP@R]K^]J\[HYZHYZGY[HZ[HZ[IZ[IZ[HYYFXWETXEU]GZ]HZ]I[[IZ]HY\GX]J[]I[_L]]J[]J[ZGXXEWWFUZHWXETVCQWDRYES]I\fTjeTg]M_YGWQ>KP=LL:HJ>I         "#B5BB5CA4DC5DB5C@3Cx`sWGT  !#"#!######      % '%%%.7}{nbp|q~aTexevpqvbt}kzwetdUepl{+5Fb^tj]s~joqqPMZ!! "!"% & "  !!  !8-9A2BH8HI9HJ9JH8GF6EE3CF4DF6DC4B=/<3'46-=LE\KCYOG__VobXr_So\Pki[vtdygmsP>NTBRVCUWDTWDWZFYZFY\H\\I\]J]]I][G\\H\\I\[H][H]^K^]J][J\XEXUEWUEVWFYXFYYGYYFZ[H]\I^[I[ZI[[I[\J]RATN?OWFWZHZ]K]\I\ZHZZGXXFWZHZZGXZHZZGXZGZZGYYFVWDT\IXZGXZFX[HY_L]cN_cO`aM^_J\bN_]J[^J[ZHYZHWYGWYGVYFUWDST@OUAQcSgh[rl^uj[s[K]R@OO=KL1@{g~UHW#)%,%.&.'/'0(1'/(0)/)/&,'.'.%-%-&.(/'0!''0-7}z_Ycyvo{%-6.1<65?96A:7@64=./868?MQ>MQAPQ@MQ@NP?LM=JLNOAQP@R|hVIY,-7/3?03?03?05A25C5:H49H59I3:I/8D.5B.6C+4A+3?'3<&1;%0;#09#/9$19$/:$1=ggyZKUz`_mILZLNaoe|wf}olppFCN"""""  ""! ! &%*:/SFXZLaZKaTEYL>PE8JRF[WI_[MdVJ_XJaJSK=SQDYRDXVG\\Nb_RgZNcVJ`VJ_[Mb[Mc`RjbSkjZsfVn\MdfVnl\tj[reUl_Pg\Pf\Of^PhbSkgWodUl_PeWG[TFYSFYJ>OI>LGGB?H@=F>;E76=35<;7@I>LM=MQAPMNM>OO?PWEWWEXYHZZJZXHYREV]OdeWlcTkfYpk]vn^viZqfWoiZq9.::/2@TDVZGZTCRUFVRAQO?OJ2A7,95+9=3BB7FA6DF8IB3C@1?>1?K=ML?RVH\TG]TGZbRhgVm^McZI^\KacSieTkbPfaPe^Na`Od\LaQCTE9ID8IPBUNARG1=^PedTi^ObYH\UDUUDUeRfn[ru`xvbyxczuaxq]rn[piWldTir`yvc}fVm]MajZmhWl^La`Nbrawq_uwd{ubz}hxf{rawiXlhYkp_wp_wm]s[K^YH\VH[ZJ^cRfZJ][H[^L^SBRP?MiXldTgK=LPAQI:IWEVWDVO>N8,8=2@XGZYGZ]L^TFURDSVHYVH[RDVSEVRCTZJ\PBRM=MMOD6FL=NUEX^Ma\L^QASM=NUEWWFYXGZbOcaPd\K]aPacQecQedSeaN`]K\G8JJ;LTCVZG[\I\]J]`L`bNb\H[G9JJNL>OH:JC5D6+8A5CTDWVGZQCURCVM?QI:KF9IN@QPDWJ?P9/=;0?C8IH=MJ=N>3B>2A3(4?4BH3BA6FA5FNBSSFYWI_bShdTj`OfcQhcPgcQhaRh]Mc[K`]M`\K^aPe\Ma\K_SCVH;LE:IE8HL?PPCSG:J7+8C7EL>MTFWE8FTCTSDUKOQBTUEWNAQI=MD7GQAT[K`cSfK=MNARVFX]L`UGYNAPK=LLQWFYTDVTDV]M^[J\VEXXGYYGYTCUaQd]L_UFVH:H@2?P@QVDVM=NLMN?QH;J3(27*5NAQTEWN>O[J\VFZQATM@QQDWNARJ=NK>PI4DH;NOBVOCVG:KD7GA6DF;JMAQD:IH:KZJ_^Nc_NccQfbPddRgeSi]L_[K^eSj[K^IG;KREWO@Q^MbgVliWlm\tZLaXI^_OeZJ_L=PTFYD9J?2AB6FA6DH;MK?QD8FF8IC8IE;JE9HE7GIMPCTOARQCSQBTOBSHOK=NQBRM>NNARL?NI;KKPPARN>NG9IH9JK:MO?QJ>QOCVF:J9,:@3C\K_`NdUFYWEWQ@TI:MKOM@QH;KM?QF:JM@RPCWGO[NaVI\QDVSEXOASRCTTDXUEY]MaYI[[K]XIZO@RN?PF9HC5DE7FE9IF9JI=NA6GF:KTGYP@Q\K__OdVEW\MbHPD7GC8HHOPCTOAQF9I@5EF;KD8GHNOASQCTPCUPBUN?QJNE8F=1?B6ESDTXI[/"-B6F_OeTDVP?OSBSSBSQ?QQARRASTCTN>PSCUSDV\Ma_Na_L`^K`]K^dQdaOc\K^XHZWEXTCTWEWP>OUDV]M`\K_ZH[UFWTDUTBTQARL=NRASUDUUEWQ@SQ@RP?QG7IH:LJ;L>3D<1BC4DRCV^MadQfcQfcPf\K`UEYPBUOATM?QJ?OC7EN?RTFYRBUWG[TEXQDVSDXL=QL=PTDVYJ]WI^XH]WH]UFYVFYL=OO@SQBSK=NK=MI;LF:JF9I:.OKNXGZWFYSDTJOP=NK:KP@RSBTYGZRASO@RJQSDWUCXYI^WH\OARUFZ\KbPBUG:IC7FF9ID9IC7GK>MK>OK?QK?QREXWH\]M`\La]Mb^OdXJ\^NbbShYI^YI^\L`UEVTEXXI\YJ\]N`^ObZJ^YK^XJ^SEY^OdTFYUHZXK]XJZVGZ`RfXJ]WJ[\M`UHZZK^`QffUkeTjaPfgWkiXnjXngWnfVmbRijZoeTibQedRieTkbRe]N_ZK]M?OB3B^NaYH[YI[\J]ZJ^bRfcQg]K`[I\QBSJ=NUGZZK]_OacSemYokXm\K^RBSM>OVGZM>N?0=@0>RCURCUI=LSFVYJ^^NaYIZSBV>1OWH[O?PM>MN>MM;JSAQF6B<0:E8HD8HNF8HJOUDVTDVSDURDTRAU_M`aOcbOd]L`]Ka^K`WFZYK^TDVTDXSDYRDWWG]RCVPBUPATTEZVG\WF\[J`^NdYI^VFZQ@VN?RUE[SCXSCWTHZSEXK=OF7HE7GD8GB7GF;K=3BL>OUFYPBSM?QPCWJ?SSFZ[L_UFXTEXQBTVGZUFYXI[RBTZJ][J`XH\TEY`Oc`M``NbbPc^Mc[K_TEYH;KTEXUFXUFW_Nb\LaYH]\K`VGZUGZPCURCWWH\VEW`Na[J]cRfbNdeSheTjhXnjYohUjlZofTjjXocRg_NbVDXSCVRBTSEVOBRXGY[K]jWiZI[\K`YI]UEY_Na`Pb[L]QCU[K^XI[WGYWEW]K`aNbTBSQ@QOBSVGZUFWRDUXHZYI\]L^XFXN@PQCSeTieShaNbVEX[J^VFYPBRIOP@RN@QJ=MK?OL@QPASOARQCUYI^dShaNcXFYZHZ]K^[I\F7GO@QaQdcQf`NdYI]YJ]UFXQBTVEW\K^^NaaPd[J][K\XFWXGXWFYXGYVHXSCSZJ\\K_WFZ]MaWEWP?QQAQQ@QO@QTEVUFWTDXTCWUCVN>NVFYN?PWFXSAUMPM@QO@SVFZSDWVGYPBTTEWRDUSFXRFXUFXXFX]K_]K_fUkfTj_Pe\MacSi\L_[K^aQf`NdYH\WH\YI^XJ\WI^ZK`bRgfTiaPc]L__Na]K__Lb\K^`NbaNbcQdXGXdRggTjeSibPd_OeaQf`NcbQg`OdbPd`Nb]J\VDVYH\]Mb\La_Na]L_[J]RCTN?PVGYYH\UDV\J`XFYL;LP@QSEV^Pc]Oa\L_YJ[XGY^K]UCTI;IK=LUGXQCSZI[ZHZ_L_VDVUDVZI[XFXTETL;JM?OTDVO?PN>NF8GINIOJ:KLPI9IRBSSBTN>NP?RLPM?RTEZSEXM@SPBUG:KOATJ;NF:KRDWYI]\LaZJ^WFZXG]WG[WHZPBSN@RXH]cQg]Mb_Oc\MaXJ]RDVTG[L@QXJ[SCUWH[VEZdQf]M_cRhcQf]Ma_MbgVjaPc_LaUDV_Od`OeXH]^MccQgeTieThZJ\UFXSATSATQ@SRCT]L`gTifTjaPfbPgdRgdSheTicQfaOd\K_\K_^Ma`Oc_Na[L]XGY`Oc]Lb`Nc]K_^L`[I_UEYWH[TEXWGZSEW[J]]K`ZI^aPefTjfVkbPdYHYWGYWGYbNagTgXFZVFW]Ma[K^VEW\K]aObbOc^K_aOcP>P;-8L>LN>NH:HJ;JRDUPCTQDVXGZWGYRDVXI\ZI[VGXXHYZH[[H[_L`_LaeSg`MabNdaObJ:KF7H[J_^La_Mb]Mb]McTEY[K^]L_\K][J]VFWQASO>OH9HL>NP@QUFWWF[UFZ[K`]K`\K`ZJ^UEWRBUOASL>NO?ORBTTDWO?QJPN?QN?QJPF9ILOJ;LUFYUCWUDVVEWL1?@2?LN;.:J;LYG[\K^ZJ_XH\VGY\L`]L`UDUTCVWGZVGYXHZQCUSEWP@RYH\VEYVEYZJ^WF[UEXSCVWGYYI]SCTSEWUGXN?PL=OM>QP@SSCUP?RO>OL;LH8IC4GJ;KM>PG7IJ9IF6FF7GKPTDVPASO@RUEXZI]PARP?QQARN>OQBTQASJ:HK=NQ?RR@RL:KSDVMPTEWM@O1>A2BK=NSCUK:KN>PSCXWF\[J^UCV^K^ZG[SARJ:IN?MWGUSBSVGYSDWSBTM>MSCTPATMN\J]ZHZ\K^P@PQ@RRBQOAQQBSN>OR@ReRdYHYXFXZI[^K]^L_\J\`Ob[I\RAQN>M[JZUEVP?OVDUUBSTCUVEXRAS[H[]J]]J^SCSQBRTDUVFWVEWXGX\J]^K^WEVUCUZHZWFY_Ma\I^YFX\HZbNc^K^XFWRARUDUTBRYGYYGYUEUTBSVEVYHZ[K\YGYRASR@PQ@QZJ\TDUMPRCVQAUWFZZI]WEXWEZWG\N?SSBVTEYK=OL?PRDVL>NJ;KJ9KWFXZH\VFXXI[\LaVEXN>ON>OXHZVEWSBSP@QQBSSCUTCUUCUZH\>/H9GI:HUFWSCTN>OQBSF8GG9IB4D@3@A3@L>LO?LO>LSBRN?ORBSUCVTDWSDWI:LG8FO?OM=NE6FG7FSASO@QL1>XGYTCUUDVUEWSBTP@PJ=LJ=MI:JQ@Q`M`YGYJ9HZG[SAS^M`SBSYGZSCTUFWO@NK=IF6ETDUYFYUCTRARSBSTCUYH[\K\WFWXGYXGYSCTQBRTDUWGYUEVO@PXGYZHZVEVQ@P^K^bOafQfdPd_L_ZIZR@RP?QVEVSBRUDTZH[K9IF7DL;KSARWGXZGYWEWUBTZF[VEXP?PLOR@QO?OM>NQAR^L]\J\YHXZHZ]J][H[\K\]J]]J\]J^_L`TASE4BC5CN=PMPRCTO?QRBSWGYYI[ZHZWEV[HZVEWRBRUCVYGZTCSSARL=MLNN?QKOM>MJ;JJ;JVEXWFYUEYUEWUDWSBSXEXVEYJ:HRBSN>OG7GJ:IF6EF6E?0?B2AKD7FH;K@2AJ;LQASVEX]M_O?OTCTTDTLMH8ITDUK>LH:IH9JN?OH8HSDVWGZUFWRBTL=LE8FN@QO@PWFXWFW[I[PAQUEVUCV`OcYH[YG[UEWO?OJ9GM=LM>NLNLPSBSVGXZHZ\J\]K\dQd[HXVCTXCVWEVXFW_L`^J^]J]ZG[]J[G5F?.>PASN=ORBVWFYUDWTDVSCTRASK:KN?OWGYYHZYGZWEWYGZUDV[J\VEUWEVXEWSAPQ@QSCSVCVVBUVDVTDVP@PK;KRCTL;KWEXSARL;MM=NH8IF5FF6H \ No newline at end of file diff --git a/src/examples/svgs/scion.svg b/src/examples/images/scion.svg similarity index 100% rename from src/examples/svgs/scion.svg rename to src/examples/images/scion.svg diff --git a/src/examples/svgs/tiger.svg b/src/examples/images/tiger.svg similarity index 100% rename from src/examples/svgs/tiger.svg rename to src/examples/images/tiger.svg diff --git a/src/examples/svgs/yadis.svg b/src/examples/images/yadis.svg similarity index 100% rename from src/examples/svgs/yadis.svg rename to src/examples/images/yadis.svg diff --git a/src/examples/svgs/yinyang.svg b/src/examples/images/yinyang.svg similarity index 100% rename from src/examples/svgs/yinyang.svg rename to src/examples/images/yinyang.svg diff --git a/src/examples/meson.build b/src/examples/meson.build index bb9d576d..1385a749 100644 --- a/src/examples/meson.build +++ b/src/examples/meson.build @@ -17,6 +17,7 @@ source_file = [ 'Opacity.cpp', 'PathCopy.cpp', 'Path.cpp', + 'PixelImage.cpp', 'RadialGradient.cpp', 'Scene.cpp', 'SceneTransform.cpp', diff --git a/src/lib/gl_engine/tvgGlRenderer.cpp b/src/lib/gl_engine/tvgGlRenderer.cpp index 4963c7e7..79ba1fa5 100644 --- a/src/lib/gl_engine/tvgGlRenderer.cpp +++ b/src/lib/gl_engine/tvgGlRenderer.cpp @@ -130,7 +130,7 @@ bool GlRenderer::render(const Shape& shape, void* data) } -bool GlRenderer::dispose(TVG_UNUSED const Shape& shape, void *data) +bool GlRenderer::dispose(void *data) { GlShape* sdata = static_cast(data); if (!sdata) return false; diff --git a/src/lib/sw_engine/meson.build b/src/lib/sw_engine/meson.build index 39536436..7357a887 100644 --- a/src/lib/sw_engine/meson.build +++ b/src/lib/sw_engine/meson.build @@ -1,6 +1,7 @@ source_file = [ 'tvgSwCommon.h', 'tvgSwFill.cpp', + 'tvgSwImage.cpp', 'tvgSwMath.cpp', 'tvgSwRenderer.h', 'tvgSwRaster.cpp', diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 6e262246..595df607 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -212,6 +212,16 @@ struct SwShape bool rect; //Fast Track: Othogonal rectangle? }; +struct SwImage +{ + SwOutline* outline = nullptr; + SwRleData* rle = nullptr; + uint32_t* data = nullptr; + SwBBox bbox; + uint32_t width; + uint32_t height; +}; + struct SwCompositor { uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a); @@ -284,6 +294,14 @@ bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline); SwOutline* strokeExportOutline(SwStroke* stroke, unsigned tid); void strokeFree(SwStroke* stroke); +bool imagePrepare(SwImage* image, const Picture* pdata, unsigned tid, const SwSize& clip, const Matrix* transform); +bool imagePrepared(SwImage* image); +bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwSize& clip, bool antiAlias, bool hasComposite); +void imageDelOutline(SwImage* image, uint32_t tid); +void imageReset(SwImage* image); +bool imageGenOutline(SwImage* image, const Picture* pdata, unsigned tid, const Matrix* transform); +void imageFree(SwImage* image); + bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, SwSurface* surface, bool ctable); void fillReset(SwFill* fill); void fillFree(SwFill* fill); @@ -307,6 +325,7 @@ void mpoolRetStrokeOutline(unsigned idx); bool rasterCompositor(SwSurface* surface); bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id); bool rasterSolidShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); +bool rasterImage(SwSurface* surface, SwImage* image, uint8_t opacity, const Matrix* transform); bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); bool rasterClear(SwSurface* surface); @@ -335,4 +354,14 @@ static inline void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, in #endif } +static inline SwPoint mathTransform(const Point* to, const Matrix* transform) +{ + if (!transform) return {TO_SWCOORD(to->x), TO_SWCOORD(to->y)}; + + auto tx = ((to->x * transform->e11 + to->y * transform->e12 + transform->e13) + 0.5f); + auto ty = ((to->x * transform->e21 + to->y * transform->e22 + transform->e23) + 0.5f); + + return {TO_SWCOORD(tx), TO_SWCOORD(ty)}; +} + #endif /* _TVG_SW_COMMON_H_ */ diff --git a/src/lib/sw_engine/tvgSwImage.cpp b/src/lib/sw_engine/tvgSwImage.cpp new file mode 100644 index 00000000..ac75097e --- /dev/null +++ b/src/lib/sw_engine/tvgSwImage.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include "tvgSwCommon.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + + +static void _initBBox(SwBBox& bbox) +{ + bbox.min.x = bbox.min.y = 0; + bbox.max.x = bbox.max.y = 0; +} + + +static bool _updateBBox(SwOutline* outline, SwBBox& bbox, const SwSize& clip) +{ + if (!outline) return false; + + auto pt = outline->pts; + + if (outline->ptsCnt <= 0) { + _initBBox(bbox); + return false; + } + + auto xMin = pt->x; + auto xMax = pt->x; + auto yMin = pt->y; + auto yMax = pt->y; + + ++pt; + + for(uint32_t i = 1; i < outline->ptsCnt; ++i, ++pt) { + if (xMin > pt->x) xMin = pt->x; + if (xMax < pt->x) xMax = pt->x; + if (yMin > pt->y) yMin = pt->y; + if (yMax < pt->y) yMax = pt->y; + } + bbox.min.x = xMin >> 6; + bbox.max.x = (xMax + 63) >> 6; + bbox.min.y = yMin >> 6; + bbox.max.y = (yMax + 63) >> 6; + + bbox.min.x = max(bbox.min.x, TO_SWCOORD(0)); + bbox.min.y = max(bbox.min.y, TO_SWCOORD(0)); + bbox.max.x = min(bbox.max.x, clip.w); + bbox.max.y = min(bbox.max.y, clip.h); + + if (xMax - xMin < 1 && yMax - yMin < 1) return false; + + return true; +} + + +static bool _checkValid(const SwOutline* outline, const SwBBox& bbox, const SwSize& clip) +{ + if (outline->ptsCnt == 0 || outline->cntrsCnt <= 0) return false; + + //Check boundary + if (bbox.min.x >= clip.w || bbox.min.y >= clip.h || bbox.max.x <= 0 || bbox.max.y <= 0) return false; + + return true; +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + + +bool imagePrepare(SwImage* image, const Picture* pdata, unsigned tid, const SwSize& clip, const Matrix* transform) +{ + if (!imageGenOutline(image, pdata, tid, transform)) return false; + + if (!_updateBBox(image->outline, image->bbox, clip)) return false; + + if (!_checkValid(image->outline, image->bbox, clip)) return false; + + return true; +} + + +bool imagePrepared(SwImage* image) +{ + return image->rle ? true : false; +} + + +bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwSize& clip, bool antiAlias, bool hasComposite) +{ + if ((image->rle = rleRender(image->rle, image->outline, image->bbox, clip, antiAlias))) return true; + + return false; +} + + +void imageDelOutline(SwImage* image, uint32_t tid) +{ + mpoolRetOutline(tid); + image->outline = nullptr; +} + + +void imageReset(SwImage* image) +{ + rleReset(image->rle); + image->rle = nullptr; + _initBBox(image->bbox); +} + + +bool imageGenOutline(SwImage* image, const Picture* pdata, unsigned tid, const Matrix* transform) +{ + image->outline = mpoolReqOutline(tid); + auto outline = image->outline; + + float w, h; + pdata->viewbox(nullptr, nullptr, &w, &h); + if (w == 0 || h == 0) return false; + + outline->reservedPtsCnt = 5; + outline->pts = static_cast(realloc(outline->pts, outline->reservedPtsCnt * sizeof(SwPoint))); + outline->types = static_cast(realloc(outline->types, outline->reservedPtsCnt * sizeof(uint8_t))); + + outline->reservedCntrsCnt = 1; + outline->cntrs = static_cast(realloc(outline->cntrs, outline->reservedCntrsCnt * sizeof(uint32_t))); + + Point to[4] = {{0 ,0}, {w, 0}, {w, h}, {0, h}}; + for (int i = 0; i < 4; i++) { + outline->pts[outline->ptsCnt] = mathTransform(&to[i], transform); + outline->types[outline->ptsCnt] = SW_CURVE_TYPE_POINT; + ++outline->ptsCnt; + } + + outline->pts[outline->ptsCnt] = outline->pts[0]; + outline->types[outline->ptsCnt] = SW_CURVE_TYPE_POINT; + ++outline->ptsCnt; + + outline->cntrs[outline->cntrsCnt] = outline->ptsCnt - 1; + ++outline->cntrsCnt; + + outline->opened = false; + image->outline = outline; + + image->width = w; + image->height = h; + return true; +} + +void imageFree(SwImage* image) +{ + rleFree(image->rle); +} diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 92c3f613..55e808b3 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -22,6 +22,7 @@ #include "tvgSwCommon.h" #include "tvgRender.h" #include +#include /************************************************************************/ /* Internal Class Implementation */ @@ -45,6 +46,39 @@ static uint32_t _argbJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a) } +static void _inverse(const Matrix* transform, Matrix* invM) +{ + // computes the inverse of a matrix m + auto det = transform->e11 * (transform->e22 * transform->e33 - transform->e32 * transform->e23) - + transform->e12 * (transform->e21 * transform->e33 - transform->e23 * transform->e31) + + transform->e13 * (transform->e21 * transform->e32 - transform->e22 * transform->e31); + + auto invDet = 1 / det; + + invM->e11 = (transform->e22 * transform->e33 - transform->e32 * transform->e23) * invDet; + invM->e12 = (transform->e13 * transform->e32 - transform->e12 * transform->e33) * invDet; + invM->e13 = (transform->e12 * transform->e23 - transform->e13 * transform->e22) * invDet; + invM->e21 = (transform->e23 * transform->e31 - transform->e21 * transform->e33) * invDet; + invM->e22 = (transform->e11 * transform->e33 - transform->e13 * transform->e31) * invDet; + invM->e23 = (transform->e21 * transform->e13 - transform->e11 * transform->e23) * invDet; + invM->e31 = (transform->e21 * transform->e32 - transform->e31 * transform->e22) * invDet; + invM->e32 = (transform->e31 * transform->e12 - transform->e11 * transform->e32) * invDet; + invM->e33 = (transform->e11 * transform->e22 - transform->e21 * transform->e12) * invDet; +} + + +static bool _identify(const Matrix* transform) +{ + if (!transform || + transform->e11 != 1.0f || transform->e12 != 0.0f || transform->e13 != 0.0f || + transform->e21 != 0.0f || transform->e22 != 1.0f || transform->e23 != 0.0f || + transform->e31 != 0.0f || transform->e32 != 0.0f || transform->e33 != 1.0f) + return false; + + return true; +} + + static SwBBox _clipRegion(Surface* surface, SwBBox& in) { auto bbox = in; @@ -108,6 +142,141 @@ static bool _rasterTranslucentRle(SwSurface* surface, SwRleData* rle, uint32_t c } +static bool _rasterTranslucentImageRle(SwSurface* surface, SwRleData* rle, uint32_t *img, uint32_t opacity, const Matrix* invTransform, uint32_t w, uint32_t h) +{ + auto span = rle->spans; + + for (uint32_t i = 0; i < rle->size; ++i) { + for (uint32_t x = 0; x < span->len; ++x) { + auto rX = static_cast(roundf((span->x + x) * invTransform->e11 + span->y * invTransform->e12 + invTransform->e13)); + auto rY = static_cast(roundf((span->x + x) * invTransform->e21 + span->y * invTransform->e22 + invTransform->e23)); + + if (rX < 0 || rX >= w || rY < 0 || rY >= h) continue; + + auto dst = &surface->buffer[span->y * surface->stride + span->x + x]; + auto index = rY * w + rX; //TODO: need to use image's stride + if (dst && img && img[index]) { + auto alpha = ALPHA_MULTIPLY(span->coverage, opacity); + auto src = ALPHA_BLEND(img[index], alpha); + auto invAlpha = 255 - surface->comp.alpha(src); + *dst = src + ALPHA_BLEND(*dst, invAlpha); + } + } + ++span; + } + return true; +} + + +static bool _rasterImageRle(SwSurface* surface, SwRleData* rle, uint32_t *img, const Matrix* invTransform, uint32_t w, uint32_t h) +{ + if (!rle) return false; + + auto span = rle->spans; + + for (uint32_t i = 0; i < rle->size; ++i) { + for (uint32_t x = 0; x < span->len; ++x) { + auto rX = static_cast(roundf((span->x + x) * invTransform->e11 + span->y * invTransform->e12 + invTransform->e13)); + auto rY = static_cast(roundf((span->x + x) * invTransform->e21 + span->y * invTransform->e22 + invTransform->e23)); + + if (rX < 0 || rX >= w || rY < 0 || rY >= h) continue; + + auto dst = &surface->buffer[span->y * surface->stride + span->x + x]; + auto index = rY * w + rX; //TODO: need to use image's stride + if (dst && img && img[index]) { + auto src = ALPHA_BLEND(img[index], span->coverage); + auto invAlpha = 255 - surface->comp.alpha(src); + *dst = src + ALPHA_BLEND(*dst, invAlpha); + } + } + ++span; + } + return true; +} + + +static bool _rasterTranslucentImage(SwSurface* surface, uint32_t *img, uint32_t opacity,const SwBBox& region, const Matrix* invTransform, uint32_t w, uint32_t h) +{ + for (auto y = region.min.y; y < region.max.y; y++) { + for (auto x = region.min.x; x < region.max.x; x++) { + auto rX = static_cast(roundf(x * invTransform->e11 + y * invTransform->e12 + invTransform->e13)); + auto rY = static_cast(roundf(x * invTransform->e21 + y * invTransform->e22 + invTransform->e23)); + + if (rX < 0 || rX >= w || rY < 0 || rY >= h) continue; + + auto dst = &surface->buffer[y * surface->stride + x]; + auto index = rX + (rY * w); //TODO: need to use image's stride + if (dst && img && img[index]) { + auto src = ALPHA_BLEND(img[index], opacity); + auto invAlpha = 255 - surface->comp.alpha(src); + *dst = src + ALPHA_BLEND(*dst, invAlpha); + } + } + } + return true; +} + + +static bool _rasterImage(SwSurface* surface, uint32_t *img, const SwBBox& region, uint32_t w, uint32_t h) +{ + for (auto y = region.min.y; y < region.max.y; y++) { + for (auto x = region.min.x; x < region.max.x; x++) { + auto dst = &surface->buffer[y * surface->stride + x]; + auto index = x + (y * w); //TODO: need to use image's stride + if (dst && img && img[index]) { + auto src = img[index]; + auto invAlpha = 255 - surface->comp.alpha(src); + *dst = src + ALPHA_BLEND(*dst, invAlpha); + } + } + } + return true; +} + + +static bool _rasterImage(SwSurface* surface, uint32_t *img, const SwBBox& region, const Matrix* invTransform, uint32_t w, uint32_t h) +{ + for (auto y = region.min.y; y < region.max.y; y++) { + for (auto x = region.min.x; x < region.max.x; x++) { + auto rX = static_cast(roundf(x * invTransform->e11 + y * invTransform->e12 + invTransform->e13)); + auto rY = static_cast(roundf(x * invTransform->e21 + y * invTransform->e22 + invTransform->e23)); + + if (rX < 0 || rX >= w || rY < 0 || rY >= h) continue; + + auto dst = &surface->buffer[y * surface->stride + x]; + auto index = rX + (rY * w); //TODO: need to use image's stride + if (dst && img && img[index]) { + auto src = img[index]; + auto invAlpha = 255 - surface->comp.alpha(src); + *dst = src + ALPHA_BLEND(*dst, invAlpha); + } + } + } + return true; +} + + +bool rasterImage(SwSurface* surface, SwImage* image, uint8_t opacity, const Matrix* transform) +{ + Matrix invTransform; + _inverse(transform, &invTransform); + if (image->rle) { + if (opacity < 255) return _rasterTranslucentImageRle(surface, image->rle, image->data, opacity, &invTransform, image->width, image->height ); + return _rasterImageRle(surface, image->rle, image->data, &invTransform, image->width, image->height ); + } + else { + // Fast track + if (_identify(transform)) { + return _rasterImage(surface, image->data, image->bbox, image->width, image->height); + } + else { + if (opacity < 255) return _rasterTranslucentImage(surface, image->data, opacity, image->bbox, &invTransform, image->width, image->height); + return _rasterImage(surface, image->data, image->bbox, &invTransform, image->width, image->height); + } + } +} + + static bool _rasterSolidRle(SwSurface* surface, SwRleData* rle, uint32_t color) { if (!rle) return false; @@ -368,4 +537,4 @@ bool rasterClear(SwSurface* surface) } } return true; -} \ No newline at end of file +} diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index 83fcada1..daf65f00 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -31,14 +31,21 @@ static uint32_t rendererCnt = 0; struct SwTask : Task { - SwShape shape; - const Shape* sdata = nullptr; Matrix* transform = nullptr; SwSurface* surface = nullptr; RenderUpdateFlag flags = RenderUpdateFlag::None; vector compList; uint32_t opacity; + virtual bool dispose() = 0; +}; + + +struct SwShapeTask : SwTask +{ + SwShape shape; + const Shape* sdata = nullptr; + void run(unsigned tid) override { if (opacity == 0) return; //Invisible @@ -52,7 +59,7 @@ struct SwTask : Task SwSize clip = {static_cast(surface->w), static_cast(surface->h)}; - //Invisiable shape turned to visible by alpha. + //invisible shape turned to visible by alpha. auto prepareShape = false; if (!shapePrepared(&shape) && ((flags & RenderUpdateFlag::Color) || (opacity > 0))) prepareShape = true; @@ -98,7 +105,7 @@ struct SwTask : Task //Composition for (auto comp : compList) { - SwShape *compShape = &static_cast(comp.edata)->shape; + SwShape *compShape = &static_cast(comp.edata)->shape; if (comp.method == CompositeMethod::ClipPath) { //Clip to fill(path) rle if (shape.rle && compShape->rect) rleClipRect(shape.rle, &compShape->bbox); @@ -112,8 +119,61 @@ struct SwTask : Task end: shapeDelOutline(&shape, tid); } + + bool dispose() override + { + shapeFree(&shape); + return true; + } }; + +struct SwImageTask : SwTask +{ + SwImage image; + const Picture* pdata = nullptr; + uint32_t *pixels = nullptr; + + void run(unsigned tid) override + { + SwSize clip = {static_cast(surface->w), static_cast(surface->h)}; + + //Invisiable shape turned to visible by alpha. + auto prepareImage = false; + if (!imagePrepared(&image) && ((flags & RenderUpdateFlag::Image) || (opacity > 0))) prepareImage = true; + + if (prepareImage) { + imageReset(&image); + if (!imagePrepare(&image, pdata, tid, clip, transform)) goto end; + + if (compList.size() > 0) { + if (!imageGenRle(&image, pdata, clip, false, true)) goto end; + + //Composition + for (auto comp : compList) { + SwShape *compShape = &static_cast(comp.edata)->shape; + if (comp.method == CompositeMethod::ClipPath) { + //Clip to fill(path) rle + if (image.rle && compShape->rect) rleClipRect(image.rle, &compShape->bbox); + else if (image.rle && compShape->rle) rleClipPath(image.rle, compShape->rle); + } + } + } + } + + if (this->pixels) image.data = this->pixels; + end: + imageDelOutline(&image, tid); + } + + bool dispose() override + { + imageFree(&image); + return true; + } +}; + + static void _termEngine() { if (rendererCnt > 0) return; @@ -178,9 +238,17 @@ bool SwRenderer::postRender() } -bool SwRenderer::render(const Shape& shape, void *data) +bool SwRenderer::render(TVG_UNUSED const Picture& picture, void *data) { - auto task = static_cast(data); + auto task = static_cast(data); + task->done(); + + return rasterImage(surface, &task->image, task->opacity, task->transform); +} + +bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data) +{ + auto task = static_cast(data); task->done(); uint8_t r, g, b, a; @@ -200,13 +268,13 @@ bool SwRenderer::render(const Shape& shape, void *data) } -bool SwRenderer::dispose(TVG_UNUSED const Shape& sdata, void *data) +bool SwRenderer::dispose(void *data) { auto task = static_cast(data); if (!task) return true; task->done(); - shapeFree(&task->shape); + task->dispose(); if (task->transform) free(task->transform); delete(task); @@ -214,25 +282,11 @@ bool SwRenderer::dispose(TVG_UNUSED const Shape& sdata, void *data) } -void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* transform, uint32_t opacity, vector& compList, RenderUpdateFlag flags) +void SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, vector& compList, RenderUpdateFlag flags) { - //prepare task - auto task = static_cast(data); - if (!task) { - task = new SwTask; - if (!task) return nullptr; - } - - if (flags == RenderUpdateFlag::None) return task; - - //Finish previous task if it has duplicated request. - task->done(); - - task->sdata = &sdata; - if (compList.size() > 0) { //Guarantee composition targets get ready. - for (auto comp : compList) static_cast(comp.edata)->done(); + for (auto comp : compList) static_cast(comp.edata)->done(); task->compList.assign(compList.begin(), compList.end()); } @@ -250,6 +304,48 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* tasks.push_back(task); TaskScheduler::request(task); +} + + +void* SwRenderer::prepare(const Picture& pdata, void* data, uint32_t *pixels, const RenderTransform* transform, uint32_t opacity, vector& compList, RenderUpdateFlag flags) +{ + //prepare task + auto task = static_cast(data); + if (!task) { + task = new SwImageTask; + if (!task) return nullptr; + } + + if (flags == RenderUpdateFlag::None) return task; + + //Finish previous task if it has duplicated request. + task->done(); + + task->pdata = &pdata; + task->pixels = pixels; + + prepareCommon(task, transform, opacity, compList, flags); + + return task; +} + + +void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* transform, uint32_t opacity, vector& compList, RenderUpdateFlag flags) +{ + //prepare task + auto task = static_cast(data); + if (!task) { + task = new SwShapeTask; + if (!task) return nullptr; + } + + if (flags == RenderUpdateFlag::None) return task; + + //Finish previous task if it has duplicated request. + task->done(); + task->sdata = &sdata; + + prepareCommon(task, transform, opacity, compList, flags); return task; } @@ -283,4 +379,4 @@ SwRenderer* SwRenderer::gen() { ++rendererCnt; return new SwRenderer(); -} \ No newline at end of file +} diff --git a/src/lib/sw_engine/tvgSwRenderer.h b/src/lib/sw_engine/tvgSwRenderer.h index 06b2f0f4..3601eae6 100644 --- a/src/lib/sw_engine/tvgSwRenderer.h +++ b/src/lib/sw_engine/tvgSwRenderer.h @@ -35,12 +35,14 @@ class SwRenderer : public RenderMethod { public: void* prepare(const Shape& shape, void* data, const RenderTransform* transform, uint32_t opacity, vector& compList, RenderUpdateFlag flags) override; - bool dispose(const Shape& shape, void *data) override; + void* prepare(const Picture& picture, void* data, uint32_t *buffer, const RenderTransform* transform, uint32_t opacity, vector& compList, RenderUpdateFlag flags) override; + bool dispose(void *data) override; bool preRender() override; bool postRender() override; bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs); bool clear() override; bool render(const Shape& shape, void *data) override; + bool render(const Picture& picture, void *data) override; static SwRenderer* gen(); static bool init(uint32_t threads); @@ -52,6 +54,8 @@ private: SwRenderer(){}; ~SwRenderer(); + + void prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, vector& compList, RenderUpdateFlag flags); }; } diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index 637663a1..6a219a9d 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -19,7 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include #include "tvgSwCommon.h" #include "tvgBezier.h" @@ -34,17 +33,6 @@ struct Line }; -static SwPoint _transform(const Point* to, const Matrix* transform) -{ - if (!transform) return {TO_SWCOORD(to->x), TO_SWCOORD(to->y)}; - - auto tx = round(to->x * transform->e11 + to->y * transform->e12 + transform->e13); - auto ty = round(to->x * transform->e21 + to->y * transform->e22 + transform->e23); - - return {TO_SWCOORD(tx), TO_SWCOORD(ty)}; -} - - static float _lineLength(const Point& pt1, const Point& pt2) { /* approximate sqrt(x*x + y*y) using alpha max plus beta min algorithm. @@ -101,7 +89,7 @@ static void _outlineMoveTo(SwOutline& outline, const Point* to, const Matrix* tr { _growOutlinePoint(outline, 1); - outline.pts[outline.ptsCnt] = _transform(to, transform); + outline.pts[outline.ptsCnt] = mathTransform(to, transform); outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT; if (outline.ptsCnt > 0) { @@ -118,7 +106,7 @@ static void _outlineLineTo(SwOutline& outline, const Point* to, const Matrix* tr { _growOutlinePoint(outline, 1); - outline.pts[outline.ptsCnt] = _transform(to, transform); + outline.pts[outline.ptsCnt] = mathTransform(to, transform); outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT; ++outline.ptsCnt; } @@ -128,15 +116,15 @@ static void _outlineCubicTo(SwOutline& outline, const Point* ctrl1, const Point* { _growOutlinePoint(outline, 3); - outline.pts[outline.ptsCnt] = _transform(ctrl1, transform); + outline.pts[outline.ptsCnt] = mathTransform(ctrl1, transform); outline.types[outline.ptsCnt] = SW_CURVE_TYPE_CUBIC; ++outline.ptsCnt; - outline.pts[outline.ptsCnt] = _transform(ctrl2, transform); + outline.pts[outline.ptsCnt] = mathTransform(ctrl2, transform); outline.types[outline.ptsCnt] = SW_CURVE_TYPE_CUBIC; ++outline.ptsCnt; - outline.pts[outline.ptsCnt] = _transform(to, transform); + outline.pts[outline.ptsCnt] = mathTransform(to, transform); outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT; ++outline.ptsCnt; } diff --git a/src/lib/tvgLoader.h b/src/lib/tvgLoader.h index c02baff6..b8d348e5 100644 --- a/src/lib/tvgLoader.h +++ b/src/lib/tvgLoader.h @@ -38,13 +38,15 @@ public: virtual ~Loader() {} - virtual bool open(const char* path) = 0; - virtual bool open(const char* data, uint32_t size) = 0; + virtual bool open(const string& path) { /* Not supported */ return false; }; + virtual bool open(const char* data, uint32_t size) { /* Not supported */ return false; }; + virtual bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) { /* Not supported */ return false; }; virtual bool read() = 0; virtual bool close() = 0; - virtual unique_ptr data() = 0; + virtual const uint32_t* pixels() { return nullptr; }; + virtual unique_ptr scene() { return nullptr; }; }; } -#endif //_TVG_LOADER_H_ \ No newline at end of file +#endif //_TVG_LOADER_H_ diff --git a/src/lib/tvgLoaderMgr.cpp b/src/lib/tvgLoaderMgr.cpp index 8075e605..1bb5f07e 100644 --- a/src/lib/tvgLoaderMgr.cpp +++ b/src/lib/tvgLoaderMgr.cpp @@ -24,6 +24,7 @@ #ifdef THORVG_SVG_LOADER_SUPPORT #include "tvgSvgLoader.h" #endif +#include "tvgRawLoader.h" /************************************************************************/ /* Internal Class Implementation */ @@ -41,6 +42,10 @@ static Loader* _find(FileType type) #endif break; } + case FileType::Raw: { + return new RawLoader; + break; + } default: { break; } @@ -88,7 +93,7 @@ unique_ptr LoaderMgr::loader(const string& path) { auto loader = _find(path); - if (loader && loader->open(path.c_str())) return unique_ptr(loader); + if (loader && loader->open(path)) return unique_ptr(loader); return nullptr; } @@ -102,3 +107,13 @@ unique_ptr LoaderMgr::loader(const char* data, uint32_t size) } return nullptr; } + + +unique_ptr LoaderMgr::loader(uint32_t *data, uint32_t w, uint32_t h, bool copy) +{ + for (int i = 0; i < static_cast(FileType::Unknown); i++) { + auto loader = _find(static_cast(i)); + if (loader && loader->open(data, w, h, copy)) return unique_ptr(loader); + } + return nullptr; +} diff --git a/src/lib/tvgLoaderMgr.h b/src/lib/tvgLoaderMgr.h index a62f5ad5..8b261549 100644 --- a/src/lib/tvgLoaderMgr.h +++ b/src/lib/tvgLoaderMgr.h @@ -24,14 +24,15 @@ #include "tvgLoader.h" -enum class FileType { Svg = 0, Unknown}; +enum class FileType { Svg = 0, Raw, Unknown }; struct LoaderMgr { static bool init(); static bool term(); - static unique_ptr loader(const char* data, uint32_t size); static unique_ptr loader(const string& path); + static unique_ptr loader(const char* data, uint32_t size); + static unique_ptr loader(uint32_t* data, uint32_t w, uint32_t h, bool copy); }; #endif //_TVG_LOADER_MGR_H_ diff --git a/src/lib/tvgPicture.cpp b/src/lib/tvgPicture.cpp index 0860ff47..7ecb62e4 100644 --- a/src/lib/tvgPicture.cpp +++ b/src/lib/tvgPicture.cpp @@ -26,7 +26,7 @@ /* External Class Implementation */ /************************************************************************/ -Picture::Picture() : pImpl(new Impl()) +Picture::Picture() : pImpl(new Impl(this)) { Paint::pImpl->method(new PaintMethod(pImpl)); } @@ -60,8 +60,16 @@ Result Picture::load(const char* data, uint32_t size) noexcept } +Result Picture::load(uint32_t* data, uint32_t w, uint32_t h, bool copy) noexcept +{ + if (!data || w <= 0 || h <= 0) return Result::InvalidArguments; + + return pImpl->load(data, w, h, copy); +} + + Result Picture::viewbox(float* x, float* y, float* w, float* h) const noexcept { if (pImpl->viewbox(x, y, w, h)) return Result::Success; return Result::InsufficientCondition; -} \ No newline at end of file +} diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index 0c0f8f71..79d60f98 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -34,43 +34,61 @@ struct Picture::Impl { unique_ptr loader = nullptr; Paint* paint = nullptr; + uint32_t *pixels = nullptr; + Picture *picture = nullptr; + void *edata = nullptr; //engine data + + Impl(Picture* p) : picture(p) + { + } bool dispose(RenderMethod& renderer) { - if (!paint) return false; + if (paint) { + paint->pImpl->dispose(renderer); + delete(paint); - paint->pImpl->dispose(renderer); - delete(paint); - - return true; + return true; + } + else if (pixels) { + return renderer.dispose(edata); + } + return false; } - void reload() + uint32_t reload() { - if (loader && !paint) { - auto scene = loader->data(); - if (scene) { - paint = scene.release(); - if (!paint) return; - loader->close(); + if (loader) { + if (!paint) { + auto scene = loader->scene(); + if (scene) { + paint = scene.release(); + loader->close(); + if (paint) return RenderUpdateFlag::None; + } + } + if (!pixels) { + pixels = (uint32_t*)loader->pixels(); + if (pixels) return RenderUpdateFlag::Image; } } + return RenderUpdateFlag::None; } - - void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, vector& compList, RenderUpdateFlag flag) + void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, vector& compList, RenderUpdateFlag pFlag) { - reload(); + uint32_t flag = reload(); - if (!paint) return nullptr; - - return paint->pImpl->update(renderer, transform, opacity, compList, flag); + if (pixels) edata = renderer.prepare(*picture, edata, pixels, transform, opacity, compList, static_cast(pFlag | flag)); + else if (paint) edata = paint->pImpl->update(renderer, transform, opacity, compList, static_cast(pFlag | flag)); + return edata; } bool render(RenderMethod &renderer) { - if (!paint) return false; - return paint->pImpl->render(renderer); + if (pixels) return renderer.render(*picture, edata); + else if (paint) return paint->pImpl->render(renderer); + return false; } bool viewbox(float* x, float* y, float* w, float* h) @@ -107,6 +125,14 @@ struct Picture::Impl return Result::Success; } + Result load(uint32_t* data, uint32_t w, uint32_t h, bool copy) + { + if (loader) loader->close(); + loader = LoaderMgr::loader(data, w, h, copy); + if (!loader) return Result::NonSupport; + return Result::Success; + } + Paint* duplicate() { reload(); diff --git a/src/lib/tvgRender.h b/src/lib/tvgRender.h index 1bba9ef8..9f8ebcc5 100644 --- a/src/lib/tvgRender.h +++ b/src/lib/tvgRender.h @@ -42,7 +42,7 @@ struct Composite { CompositeMethod method; }; -enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, All = 32}; +enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, All = 64}; struct RenderTransform { @@ -66,9 +66,11 @@ class RenderMethod public: virtual ~RenderMethod() {} virtual void* prepare(TVG_UNUSED const Shape& shape, TVG_UNUSED void* data, TVG_UNUSED const RenderTransform* transform, uint32_t opacity, TVG_UNUSED vector& compList, TVG_UNUSED RenderUpdateFlag flags) { return nullptr; } - virtual bool dispose(TVG_UNUSED const Shape& shape, TVG_UNUSED void *data) { return true; } + virtual void* prepare(TVG_UNUSED const Picture& picture, TVG_UNUSED void* data, TVG_UNUSED uint32_t *buffer, TVG_UNUSED const RenderTransform* transform, TVG_UNUSED uint32_t opacity, TVG_UNUSED vector& compList, TVG_UNUSED RenderUpdateFlag flags) { return nullptr; } + virtual bool dispose(TVG_UNUSED void *data) { return true; } virtual bool preRender() { return true; } virtual bool render(TVG_UNUSED const Shape& shape, TVG_UNUSED void *data) { return true; } + virtual bool render(TVG_UNUSED const Picture& picture, TVG_UNUSED void *data) { return true; } virtual bool postRender() { return true; } virtual bool clear() { return true; } virtual bool sync() { return true; } diff --git a/src/lib/tvgShapeImpl.h b/src/lib/tvgShapeImpl.h index 372d853c..66a549ab 100644 --- a/src/lib/tvgShapeImpl.h +++ b/src/lib/tvgShapeImpl.h @@ -215,7 +215,7 @@ struct Shape::Impl bool dispose(RenderMethod& renderer) { - return renderer.dispose(*shape, edata); + return renderer.dispose(edata); } bool render(RenderMethod& renderer) diff --git a/src/loaders/meson.build b/src/loaders/meson.build index bc67b53e..345497ee 100644 --- a/src/loaders/meson.build +++ b/src/loaders/meson.build @@ -5,6 +5,8 @@ if get_option('loaders').contains('svg') == true message('Enable SVG Loader') endif +subdir('raw') + loader_dep = declare_dependency( dependencies: subloader_dep, include_directories : include_directories('.'), diff --git a/src/loaders/raw/meson.build b/src/loaders/raw/meson.build new file mode 100644 index 00000000..389c0cbf --- /dev/null +++ b/src/loaders/raw/meson.build @@ -0,0 +1,9 @@ +source_file = [ + 'tvgRawLoader.h', + 'tvgRawLoader.cpp', +] + +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/loaders/raw/tvgRawLoader.cpp b/src/loaders/raw/tvgRawLoader.cpp new file mode 100644 index 00000000..4ed475d0 --- /dev/null +++ b/src/loaders/raw/tvgRawLoader.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include +#include "tvgLoaderMgr.h" +#include "tvgRawLoader.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +RawLoader::RawLoader() +{ + +} + + +RawLoader::~RawLoader() +{ + if (copy && content) { + free((void*)content); + content = nullptr; + } +} + + +bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) +{ + if (!data || w == 0 || h == 0) return false; + + vw = w; + vh = h; + + this->copy = copy; + if (copy) { + content = (uint32_t*)malloc(sizeof(uint32_t) * vw * vh); + if (!content) return false; + memcpy((void*)content, data, sizeof(uint32_t) * vw * vh); + } + else content = data; + + return true; +} + + +bool RawLoader::read() +{ + return true; +} + + +bool RawLoader::close() +{ + return true; +} + + +const uint32_t* RawLoader::pixels() +{ + return this->content; +} diff --git a/src/loaders/raw/tvgRawLoader.h b/src/loaders/raw/tvgRawLoader.h new file mode 100644 index 00000000..8b42e2ab --- /dev/null +++ b/src/loaders/raw/tvgRawLoader.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef _TVG_RAW_LOADER_H_ +#define _TVG_RAW_LOADER_H_ + +class RawLoader : public Loader +{ +public: + const uint32_t* content = nullptr; + bool copy; + + RawLoader(); + ~RawLoader(); + + using Loader::open; + bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) override; + bool read() override; + bool close() override; + + const uint32_t* pixels() override; +}; + + +#endif //_TVG_RAW_LOADER_H_ diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 23fe67a2..a4ebdfd0 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -2483,7 +2483,7 @@ bool SvgLoader::open(const char* data, uint32_t size) } -bool SvgLoader::open(const char* path) +bool SvgLoader::open(const string& path) { ifstream f; f.open(path); @@ -2539,9 +2539,10 @@ bool SvgLoader::close() } -unique_ptr SvgLoader::data() +unique_ptr SvgLoader::scene() { this->done(); if (root) return move(root); else return nullptr; } + diff --git a/src/loaders/svg/tvgSvgLoader.h b/src/loaders/svg/tvgSvgLoader.h index 11f8f4ed..ec94619c 100644 --- a/src/loaders/svg/tvgSvgLoader.h +++ b/src/loaders/svg/tvgSvgLoader.h @@ -39,14 +39,16 @@ public: SvgLoader(); ~SvgLoader(); - bool open(const char* path) override; + using Loader::open; + bool open(const string& path) override; bool open(const char* data, uint32_t size) override; + bool header(); bool read() override; bool close() override; void run(unsigned tid) override; - unique_ptr data() override; + unique_ptr scene() override; };