diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eff2a80 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*~ +*.o +src/upiwin +src/splash.bin +buildutils/mksplash diff --git a/CODE-OF-CONDUCT.md b/CODE-OF-CONDUCT.md new file mode 100755 index 0000000..fd0edab --- /dev/null +++ b/CODE-OF-CONDUCT.md @@ -0,0 +1,57 @@ +# The Erbosoft Project Code of Conduct +## (Revised December 2019) + +For the purposes of this project, the Owner is Amy G. Bowersox/Erbosoft Metaverse Design Solutions. + +1. *The Owner owns this project.* Not you. The Owner's decisions about any aspect of the project +are *final.* +2. This Code of Conduct contains harsh language. Tough shit. Suck it up, Buttercup. +3. Anyone who is an *asshole* is **banned** *from this project.* **Permanently.** +4. This project has certain objectives. Anything outside of those objectives is *irrelevant,* +unless and until the *Owner* changes the objectives. Not you. In particular, if you’re a Social +Justice Warrior trying to join this project to spread your *bullshit,* you are *automatically +declared an asshole.* And you’re *gone.* +5. The Owner reserves the right to change this Code of Conduct as they see fit. If, however, you try +to force the Owner to change it in ways that are *offensive to them,* or that try to advance +“social justice” ideals in any way, shape, or form, you’re an *asshole.* And you’re *gone.* +6. In particular, this project explicitly *rejects* the “Open Code of Conduct” by the TODO Group, +the “Contributor Code of Merit” by Coraline Ada Ehmke, the “Citizen Code of Conduct” by +Stumptown Syndicate, and any similar “codes of conduct” that may be promulgated. Anyone complaining +about this is an *asshole,* because *who the fuck are you* to tell *the Owner* how *they* should +run *their* goddamn project? And you’re *gone.* +7. The *one and only* criterion that will be used to determine whether a contribution to this project +will be accepted is *the quality of the contribution and how well it solves the problem it was +contributed to solve.* **Period.** (“Contribution” may include code, documentation, testing, or fundraising.) +8. The *one and only* criterion that will be used to judge your worth in relation to this project is +*the quality of your contributions (as defined above) to this project.* **Period.** +9. The Owner hereby does not give *one milli-micro-nano-fraction of a* **fuck** what race you are, +what gender you are or identify as, who you want to sleep with, how old you are, what your height or +weight is, what if anything may be different about your body or brain, what language you speak, +what country you’re from, what God you pray to, where you work, how much money you have, +et fucking cetera. Is your contribution any *good?* That’s all that matters. +10. If your contribution is not accepted, and you start *whining* about how it’s “actually” because you’re +of some-or-other gender/race/religion/nationality/whatthefuckever, you are attempting to have the deck +stacked in your favor because you’re “special.” That makes you an *asshole.* And you’re *gone.* +11. Only those people who have contributed a sufficient quantity of good work to the project, +*as determined in the Owner's sole discretion,* will be allowed to assume any board position, +administrative position, or management-related role. And, any position that the Owner gives, they can +also *take away,* for any reason. Anyone who complains about this is an *asshole.* And they’re *gone.* +12. You will do your own work. If you try to pass off the work of others as your own, you’re a +fucking *plagiarist,* and also an *asshole.* And you’re *gone.* +13. If there’s a discussion that cannot be resolved within the scope of the project, +*take that shit somewhere else.* The Owner does not want your bullshit here. If you continue to spread +your bullshit here, you’re an *asshole.* And you’re *gone.* +14. As noted above, the Owner's decisions about any aspect of the project are *final.* Anyone +*pissing the Owner off* by getting all up in their face about said decisions is an *asshole.* +And they’re *gone.* +15. Any advisory boards, committees, etc., having to do with this project will answer to *the Owner.* +The Owner reserves the right to disband any such whenever the hell they feel like it. As always, anyone +complaining about this is an *asshole.* And they’re *gone.* +16. Anyone who does not approve of the objectives, direction, or attitude of this project is +free to *get the fuck out* at any time. Bye Felicia! + +Acknowlegements: +- [Why Hackers Must Eject the SJWs](http://esr.ibiblio.org/?p=6918), Eric S. Raymond +- [OSS Code of Merit](http://voxday.blogspot.com/2016/01/code-of-merit.html), Vox Day +- [A contribution policy for open source that works](https://medium.com/@jmaynard/a-contribution-policy-for-open-source-that-works-bfc4600c9d83#.dslxcx1fc), Jay Maynard +- [The Code of Merit](https://github.com/rosarior/Code-of-Merit/blob/master/CODE_OF_MERIT.md), Roberto Rosario \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100755 index 0000000..25f9fd4 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,336 @@ +GNU General Public License +========================== + +_Version 2, June 1991_ +_Copyright © 1989, 1991 Free Software Foundation, Inc.,_ +_51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA_ + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +### Preamble + +The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + +We protect your rights with two steps: **(1)** copyright the software, and +**(2)** offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + +Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and +modification follow. + +### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +**0.** This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The “Program”, below, +refers to any such program or work, and a “work based on the Program” +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term “modification”.) Each licensee is addressed as “you”. + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + +**1.** You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + +**2.** You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + +* **a)** You must cause the modified files to carry prominent notices +stating that you changed the files and the date of any change. +* **b)** You must cause any work that you distribute or publish, that in +whole or in part contains or is derived from the Program or any +part thereof, to be licensed as a whole at no charge to all third +parties under the terms of this License. +* **c)** If the modified program normally reads commands interactively +when run, you must cause it, when started running for such +interactive use in the most ordinary way, to print or display an +announcement including an appropriate copyright notice and a +notice that there is no warranty (or else, saying that you provide +a warranty) and that users may redistribute the program under +these conditions, and telling the user how to view a copy of this +License. (Exception: if the Program itself is interactive but +does not normally print such an announcement, your work based on +the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +**3.** You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + +* **a)** Accompany it with the complete corresponding machine-readable +source code, which must be distributed under the terms of Sections +1 and 2 above on a medium customarily used for software interchange; or, +* **b)** Accompany it with a written offer, valid for at least three +years, to give any third party, for a charge no more than your +cost of physically performing source distribution, a complete +machine-readable copy of the corresponding source code, to be +distributed under the terms of Sections 1 and 2 above on a medium +customarily used for software interchange; or, +* **c)** Accompany it with the information you received as to the offer +to distribute corresponding source code. (This alternative is +allowed only for noncommercial distribution and only if you +received the program in object code or executable form with such +an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + +**4.** You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + +**5.** You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +**6.** Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + +**7.** If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + +**8.** If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + +**9.** The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and “any +later version”, you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + +**10.** If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + +### NO WARRANTY + +**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + +**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +### How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the “copyright” line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w` and `show c` should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w` and `show c`; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a “copyright disclaimer” for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f951f9f --- /dev/null +++ b/Makefile @@ -0,0 +1,24 @@ +# UPIWIN - Micro Pi Windowing Framework Kernel +# Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# ------------------------------------------------------------------------ +all: + make -C buildutils all + make -C src all + +clean: + make -C buildutils clean + make -C src clean diff --git a/README.md b/README.md index 22e1f59..72c1d2e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,17 @@ # UPIWIN - Micro Pi Windows Kernel -Requirements: -- Raspberry Pi 3 with PiTFT touchscreen +*Release 0.1 - December 12, 2019* + +This project involves the development of a framework for running self-contained applications in Python +on a Raspberry Pi with LCD graphical output and touchscreen input. The ultimate goal is to produce a +framework which is flexible enough to serve any number of “appliance” needs, by using different Python +scripts over the same native-code substrate, deployed on an inexpensive embedded platform. + +## Hardware requirements + +- Raspberry Pi 3 with PiTFT touchscreen (Adafruit product ID 2423) + +## Acknowledgements + +A good portion of this code was written during the VMware Carbon Black Hackathon 3.3, December 6-13 2019. +Grateful acknowledgement is provided to VMware Carbon Black for the time to accomplish this coding. diff --git a/buildutils/Makefile b/buildutils/Makefile new file mode 100644 index 0000000..0a2906f --- /dev/null +++ b/buildutils/Makefile @@ -0,0 +1,24 @@ +# UPIWIN - Micro Pi Windowing Framework Kernel +# Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# ------------------------------------------------------------------------ +all: mkgfx + +mkgfx: mkgfx.c + gcc -o mkgfx -O -Wall -I/usr/include/libpng mkgfx.c -lpng16 -lz + +clean: + rm -f *.o mkgfx diff --git a/buildutils/mkgfx.c b/buildutils/mkgfx.c new file mode 100644 index 0000000..2d7ba04 --- /dev/null +++ b/buildutils/mkgfx.c @@ -0,0 +1,319 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#include +#include +#include +#include +#include +#include +#include + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + +#ifndef png_jmpbuf +#define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#endif + +png_structp png_ptr = NULL; +png_infop info_ptr = NULL; + +png_uint_32 width, height; +int bit_depth, color_type; +uch *image_data = NULL; + +/* returns 0 on success, -1 on error */ +int readpng_init(const char *fname, FILE *infile, ulg *pWidth, ulg *pHeight) +{ + uch sig[8]; + + fread(sig, 1, 8, infile); + if (!png_check_sig(sig, 8)) + { + fprintf(stderr, "%s: invalid PNG file signature\n", fname); + return -1; + } + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + { + fprintf(stderr, "%s: out of memory\n", fname); + return -1; + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, NULL, NULL); + fprintf(stderr, "%s: out of memory\n", fname); + return -1; + } + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fprintf(stderr, "%s: bad header in PNG image\n", fname); + return -1; + } + + png_init_io(png_ptr, infile); + png_set_sig_bytes(png_ptr, 8); + png_read_info(png_ptr, info_ptr); + + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); + *pWidth = width; + *pHeight = height; + + return 0; +} + +/* returns -1 on error, 0 otherwise (out vars not touched if we can't find background */ +int readpng_get_bgcolor(const char *fname, uch *red, uch *green, uch *blue) +{ + png_color_16p pBackground; + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fprintf(stderr, "%s: unspecified error in background reading\n", fname); + return -1; + } + + if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) + return 0; + + png_get_bKGD(png_ptr, info_ptr, &pBackground); + + if (bit_depth == 16) + { + *red = pBackground->red >> 8; + *green = pBackground->green >> 8; + *blue = pBackground->blue >> 8; + } + else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + { + if (bit_depth == 1) + *red = *green = *blue = pBackground->gray ? 255 : 0; + else if (bit_depth == 2) + *red = *green = *blue = (255/3) * pBackground->gray; + else /* bit_depth == 4 */ + *red = *green = *blue = (255/15) * pBackground->gray; + } + else + { + *red = (uch)pBackground->red; + *green = (uch)pBackground->green; + *blue = (uch)pBackground->blue; + } + + return 0; +} + +/* display_exponent == LUT_exponent * CRT_exponent */ +uch *readpng_get_image(const char *fname, double display_exponent, int *pChannels, ulg *pRowbytes) +{ + double gamma; + png_uint_32 i, rowbytes; + png_bytepp row_pointers = NULL; + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fprintf(stderr, "%s: unspecified error in image data reading\n", fname); + return NULL; + } + + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_expand(png_ptr); + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_expand(png_ptr); + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_expand(png_ptr); + if (bit_depth == 16) + png_set_strip_16(png_ptr); + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + + if (png_get_gAMA(png_ptr, info_ptr, &gamma)) + png_set_gamma(png_ptr, display_exponent, gamma); + + png_read_update_info(png_ptr, info_ptr); + + *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr); + *pChannels = (int)png_get_channels(png_ptr, info_ptr); + + if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fprintf(stderr, "%s: could not allocate image buffer\n", fname); + return NULL; + } + + if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + free(image_data); + image_data = NULL; + fprintf(stderr, "%s: could not allocate image row buffer\n", fname); + return NULL; + } + + fprintf(stderr, "image %s: chans=%d rowbytes=%u height=%u\n", fname, *pChannels, + rowbytes, height); + + for (i = 0; i < height; ++i) + row_pointers[i] = image_data + i * rowbytes; + + png_read_image(png_ptr, row_pointers); + + free(row_pointers); + row_pointers = NULL; + + png_read_end(png_ptr, NULL); + + return image_data; +} + +void readpng_cleanup(int free_image_data) +{ + if (free_image_data && image_data) + { + free(image_data); + image_data = NULL; + } + + if (png_ptr && info_ptr) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + png_ptr = NULL; + info_ptr = NULL; + } +} + +int do_convert(const char *infilename, const char *outfilename) +{ + ulg image_width, image_height, image_rowbytes, row, i; + FILE *fpin; + uch *image_data, *src; + uint16_t bred = 0, bgreen = 0, bblue = 0, buf = 0; + int image_channels, fdout; + uch bg_red=0, bg_green=0, bg_blue=0, br, bg, bb, ba; + double display_exponent = 2.2; /* a guesstimate */ + + if (!(fpin = fopen(infilename, "rb"))) + { + fprintf(stderr, "%s: could not open file\n", infilename); + return -1; + } + + if (readpng_init(infilename, fpin, &image_width, &image_height)) + { + readpng_cleanup(1); + fclose(fpin); + return -1; + } + + if (readpng_get_bgcolor(infilename, &bg_red, &bg_green, &bg_blue)) + { + readpng_cleanup(1); + fclose(fpin); + return -1; + } + + image_data = readpng_get_image(infilename, display_exponent, &image_channels, &image_rowbytes); + readpng_cleanup(0); + fclose(fpin); + if (!image_data) + return -1; + + if ((fdout = creat(outfilename, S_IREAD|S_IWRITE)) < 0) + { + free(image_data); + fprintf(stderr, "%s: could not open file\n", outfilename); + return -1; + } + + for (row = 0; row < image_height; ++row) + { + src = image_data + (row * image_rowbytes); + for (i = image_width; i > 0; --i) + { + if (image_channels == 3) + { + bred = *src++; + bgreen = *src++; + bblue = *src++; + } + else if (image_channels == 4) + { + br = *src++; + bg = *src++; + bb = *src++; + ba = *src++; + if (ba == 255) + { + bred = br; + bgreen = bg; + bblue = bb; + } + else if (ba == 0) + { + bred = bg_red; + bgreen = bg_green; + bblue = bg_blue; + } + else + { + png_composite(bred, br, ba, bg_red); + png_composite(bgreen, bg, ba, bg_green); + png_composite(bblue, bb, ba, bg_blue); + } + } + bred = (bred >> 3) & 0x1F; + bgreen = (bgreen >> 2) & 0x3F; + bblue = (bblue >> 3) & 0x1F; + buf = (bred << 11) | (bgreen << 5) | bblue; + if (write(fdout, &buf, sizeof(uint16_t)) < 0) + { + close(fdout); + free(image_data); + fprintf(stderr, "%s: error writing image data\n", outfilename); + return -1; + } + } + } + + close(fdout); + free(image_data); + return 0; +} + +int main(int argc, char *argv[]) +{ + if (argc < 3) + { + fprintf(stderr, "usage: mksplash inputfile outputfile\n"); + return EXIT_FAILURE; + } + + if (do_convert(argv[1], argv[2])) + return EXIT_FAILURE; + return EXIT_SUCCESS; +} diff --git a/docs/templates/license_header.c b/docs/templates/license_header.c new file mode 100755 index 0000000..f15cf34 --- /dev/null +++ b/docs/templates/license_header.c @@ -0,0 +1,19 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ diff --git a/docs/templates/license_header.mk b/docs/templates/license_header.mk new file mode 100755 index 0000000..d1adfbb --- /dev/null +++ b/docs/templates/license_header.mk @@ -0,0 +1,17 @@ +# UPIWIN - Micro Pi Windowing Framework Kernel +# Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# ------------------------------------------------------------------------ diff --git a/docs/templates/license_header.py b/docs/templates/license_header.py new file mode 100755 index 0000000..55d4e3d --- /dev/null +++ b/docs/templates/license_header.py @@ -0,0 +1,17 @@ +# UPIWIN - Micro Pi Windowing Framework Kernel +# Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# ------------------------------------------------------------------------ diff --git a/resources/i_clear.png b/resources/i_clear.png new file mode 100755 index 0000000..3d5a4a2 Binary files /dev/null and b/resources/i_clear.png differ diff --git a/resources/i_fillrect.png b/resources/i_fillrect.png new file mode 100755 index 0000000..5225d17 Binary files /dev/null and b/resources/i_fillrect.png differ diff --git a/resources/i_freehand.png b/resources/i_freehand.png new file mode 100755 index 0000000..eaa02a5 Binary files /dev/null and b/resources/i_freehand.png differ diff --git a/resources/i_line.png b/resources/i_line.png new file mode 100755 index 0000000..89b3651 Binary files /dev/null and b/resources/i_line.png differ diff --git a/resources/i_rect.png b/resources/i_rect.png new file mode 100755 index 0000000..08ff61c Binary files /dev/null and b/resources/i_rect.png differ diff --git a/resources/i_undo.png b/resources/i_undo.png new file mode 100755 index 0000000..62b0233 Binary files /dev/null and b/resources/i_undo.png differ diff --git a/resources/splash-erbosoft.png b/resources/splash-erbosoft.png new file mode 100644 index 0000000..f272d2f Binary files /dev/null and b/resources/splash-erbosoft.png differ diff --git a/resources/splash-vmwcblk.png b/resources/splash-vmwcblk.png new file mode 100755 index 0000000..1b33a4e Binary files /dev/null and b/resources/splash-vmwcblk.png differ diff --git a/scripts/demo1.py b/scripts/demo1.py new file mode 100755 index 0000000..a823860 --- /dev/null +++ b/scripts/demo1.py @@ -0,0 +1,293 @@ +# UPIWIN - Micro Pi Windowing Framework Kernel +# Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# ------------------------------------------------------------------------ +# Demo script that implements a simple drawing program +import upiwin + +# Save off some color values. +BLACK = upiwin.rgb(0, 0, 0) +WHITE = upiwin.rgb(255, 255, 255) +LTGRAY = upiwin.rgb(204, 204, 204) +RED = upiwin.rgb(255, 0, 0) +GREEN = upiwin.rgb(0, 255, 0) +BLUE = upiwin.rgb(0, 0, 255) +CYAN = upiwin.rgb(0, 255, 255) +MAGENTA = upiwin.rgb(255, 0, 255) +YELLOW = upiwin.rgb(255, 255, 0) + +# Get the stock bitmaps. +bmp_freehand = upiwin.Bitmap(stock='freehand') +bmp_line = upiwin.Bitmap(stock='line') +bmp_rect = upiwin.Bitmap(stock='rect') +bmp_fillrect = upiwin.Bitmap(stock='fillrect') +bmp_undo = upiwin.Bitmap(stock='undo') +bmp_clear = upiwin.Bitmap(stock='clear') + +hdc = upiwin.DevCtxt(type='screen') +hdc_bits = upiwin.DevCtxt(type='memory') + +# divide the screen into "drawing" and "command" areas +screen_rect = hdc.get_clip_rect() +drawing_rect = (screen_rect[0], screen_rect[1], screen_rect[2] - 60, screen_rect[3]) +command_rect = (drawing_rect[2], screen_rect[1], screen_rect[2], screen_rect[3]) + +# further divide up the "command" area +tool_select_rect = (command_rect[0], command_rect[1], command_rect[2], 60) +color_select_rect = (command_rect[0], 60, command_rect[2], 120) +undo_rect = (command_rect[0], 120, command_rect[2], 180) +clear_rect = (command_rect[0], 180, command_rect[2], command_rect[3]) + +def point_in_rect(rect, x, y): + return (x >= rect[0]) and (x < rect[2]) and (y >= rect[1]) and (y < rect[3]) + +# --- Backlight control --- + +backlight_level_list = [1023, 768, 512, 256] +current_backlight = 0 + +def do_backlight(): + upiwin.set_backlight_level(backlight_level_list[current_backlight]) + +def select_next_backlight(): + global current_backlight + current_backlight += 1 + if current_backlight == len(backlight_level_list): + current_backlight = 0 + do_backlight() + +# --- Color selections --- + +color_list = [WHITE, RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW] +current_color = 0 + +def draw_current_color(): + hdc.text_color = color_list[current_color] + hdc.rop2 = upiwin.R2_COPYPEN + hdc.solid_rectangle(color_select_rect[0] + 6, color_select_rect[1] + 6, color_select_rect[0] + 54, color_select_rect[1] + 54) + +def select_next_color(): + global current_color + current_color += 1 + if current_color == len(color_list): + current_color = 0 + draw_current_color() + +# --- Object drawing --- + +def draw_freehand(color, data): + hdc.text_color = color + hdc.rop2 = upiwin.R2_COPYPEN + hdc.move_to(data[0][0], data[0][1]) + for pt in data[1:]: + hdc.line_to(pt[0], pt[1]) + +def draw_line(color, data): + hdc.text_color = color + hdc.rop2 = upiwin.R2_COPYPEN + hdc.move_to(data[0][0], data[0][1]) + hdc.line_to(data[1][0], data[1][1]) + +def draw_rectangle(color, data): + hdc.text_color = color + hdc.rop2 = upiwin.R2_COPYPEN + hdc.rectangle(data[0], data[1], data[2], data[3]) + +def draw_filled_rectangle(color, data): + hdc.text_color = color + hdc.rop2 = upiwin.R2_COPYPEN + hdc.solid_rectangle(data[0], data[1], data[2], data[3]) + +def draw_object(obj): + obj['draw'](obj['color'], obj['data']) + +# --- Master object list --- + +objects_drawn = [] + +def repaint(): + global drawing_rect, objects_drawn + hdc.text_color = BLACK + hdc.rop2 = upiwin.R2_COPYPEN + hdc.solid_rectangle(drawing_rect[0], drawing_rect[1], drawing_rect[2], drawing_rect[3]) + for obj in objects_drawn: + draw_object(obj) + +def undo_last(): + global objects_drawn + if len(objects_drawn) > 0: + last = len(objects_drawn) - 1 + del objects_drawn[last] + repaint() + +def clear_all(): + global objects_drawn + if len(objects_drawn) > 0: + objects_drawn.clear() + repaint() + +# --- Graphic feedback -- + +origin_x = 0 +origin_y = 0 +current_x = 0 +current_y = 0 +freehand_points = [] + +def freehand_draw(x, y, down, up): + global current_x, current_y, freehand_points + if down: + freehand_points = [] + else: + hdc.text_color = color_list[current_color] + hdc.rop2 = upiwin.R2_COPYPEN + hdc.move_to(current_x, current_y) + hdc.line_to(x, y) + current_x = x + current_y = y + freehand_points += [(x, y)] + +def rubberband_rectangle(x, y, down, up): + global current_x, current_y + hdc.text_color = LTGRAY + hdc.rop2 = upiwin.R2_XORPEN + if not down: + hdc.rectangle(min(origin_x, current_x), min(origin_y, current_y), max(origin_x, current_x), max(origin_y, current_y)) + current_x = x + current_y = y + if not up: + hdc.rectangle(min(origin_x, current_x), min(origin_y, current_y), max(origin_x, current_x), max(origin_y, current_y)) + +def rubberband_line(x, y, down, up): + global current_x, current_y + hdc.text_color = LTGRAY + hdc.rop2 = upiwin.R2_XORPEN + if not down: + hdc.move_to(origin_x, origin_y) + hdc.line_to(current_x, current_y) + current_x = x + current_y = y + if not up: + hdc.move_to(origin_x, origin_y) + hdc.line_to(current_x, current_y) + +# --- Tool definitions --- + +def save_freehand(): + return { 'draw': draw_freehand, 'color': color_list[current_color], 'data': freehand_points } + +def save_line(): + return { 'draw': draw_line, 'color': color_list[current_color], 'data': [(origin_x, origin_y), (current_x, current_y)] } + +def save_rectangle(): + return { 'draw': draw_rectangle, 'color': color_list[current_color], + 'data': (min(origin_x, current_x), min(origin_y, current_y), max(origin_x, current_x), max(origin_y, current_y)) } + +def save_filled_rectangle(): + return { 'draw': draw_filled_rectangle, 'color': color_list[current_color], + 'data': (min(origin_x, current_x), min(origin_y, current_y), max(origin_x, current_x), max(origin_y, current_y)) } + +tool_list = [ + { 'icon': bmp_freehand, 'feedback': freehand_draw, 'save': save_freehand, 'dodraw': False }, + { 'icon': bmp_line, 'feedback': rubberband_line, 'save': save_line, 'dodraw': True }, + { 'icon': bmp_rect, 'feedback': rubberband_rectangle, 'save': save_rectangle, 'dodraw': True }, + { 'icon': bmp_fillrect, 'feedback': rubberband_rectangle, 'save': save_filled_rectangle, 'dodraw': True } + ] + +current_tool = 0 + +def draw_current_tool(): + hdc_bits.select_object(tool_list[current_tool]['icon']) + hdc.bitblt(tool_select_rect[0] + 6, tool_select_rect[1] + 6, tool_select_rect[0] + 54, tool_select_rect[1] + 54, hdc_bits, 0, 0, 0) + +def select_next_tool(): + global current_tool + current_tool += 1 + if current_tool == len(tool_list): + current_tool = 0 + draw_current_tool() + +# --- Message handlers --- + +def on_touchdown(x, y): + global origin_x, origin_y + if point_in_rect(drawing_rect, x, y): + origin_x = x + origin_y = y + tool_list[current_tool]['feedback'](x, y, True, False) + +def on_touchmove(x, y): + if point_in_rect(drawing_rect, x, y): + tool_list[current_tool]['feedback'](x, y, False, False) + +def on_touchup(x, y): + global objects_drawn + if point_in_rect(drawing_rect, x, y): + tool_list[current_tool]['feedback'](x, y, False, True) + object = tool_list[current_tool]['save']() + if tool_list[current_tool]['dodraw']: + draw_object(object) + objects_drawn += [object] + +def on_touchclick(x, y): + if point_in_rect(tool_select_rect, x, y): + select_next_tool() + elif point_in_rect(color_select_rect, x, y): + select_next_color() + elif point_in_rect(undo_rect, x, y): + undo_last() + elif point_in_rect(clear_rect, x, y): + clear_all() + +def on_button_click(button): + if button == 1: # Button 1 = Set backlight level + select_next_backlight() + if button == 4: # Button 4 = Exit app + upiwin.post_quit_message(0) + +# --- Initialize and start message loop --- + +do_backlight() + +# Draw the basic layout. +hdc.text_color = LTGRAY +hdc.rop2 = upiwin.R2_COPYPEN +hdc.rectangle(tool_select_rect[0], tool_select_rect[1], tool_select_rect[2], tool_select_rect[3]) +hdc.rectangle(color_select_rect[0], color_select_rect[1], color_select_rect[2], color_select_rect[3]) +hdc.rectangle(undo_rect[0], undo_rect[1], undo_rect[2], undo_rect[3]) +hdc.rectangle(clear_rect[0], clear_rect[1], clear_rect[2], clear_rect[3]) + +draw_current_tool() +draw_current_color() + +hdc_bits.select_object(bmp_undo) +hdc.bitblt(undo_rect[0] + 6, undo_rect[1] + 6, undo_rect[0] + 54, undo_rect[1] + 54, hdc_bits, 0, 0, 0) +hdc_bits.select_object(bmp_clear) +hdc.bitblt(clear_rect[0] + 6, clear_rect[1] + 6, clear_rect[0] + 54, clear_rect[1] + 54, hdc_bits, 0, 0, 0) + +# Main message loop +msg = {} +while upiwin.get_message(msg): + if msg['message'] == upiwin.WM_TOUCHDOWN: + on_touchdown(msg['attrs'][0], msg['attrs'][1]) + if msg['message'] == upiwin.WM_TOUCHMOVE: + on_touchmove(msg['attrs'][0], msg['attrs'][1]) + if msg['message'] == upiwin.WM_TOUCHUP: + on_touchup(msg['attrs'][0], msg['attrs'][1]) + if msg['message'] == upiwin.WM_TOUCHCLICK: + on_touchclick(msg['attrs'][0], msg['attrs'][1]) + elif msg['message'] == upiwin.WM_HWBUTTONCLICK: + on_button_click(msg['attrs'][0]) diff --git a/scripts/test_clipping.py b/scripts/test_clipping.py new file mode 100755 index 0000000..a9db639 --- /dev/null +++ b/scripts/test_clipping.py @@ -0,0 +1,52 @@ +# UPIWIN - Micro Pi Windowing Framework Kernel +# Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# ------------------------------------------------------------------------ +# Test of line clipping +import upiwin + +hdc = upiwin.DevCtxt(type='screen') +hdc.text_color = 0xFFFFFF # white +hdc.rectangle(99, 99, 200, 200) + +clip = hdc.get_clip_rect() +hdc.set_clip_rect(100, 100, 200, 200) + +hdc.text_color = 0x0000FF # red +hdc.move_to(50, 200) +hdc.line_to(200, 50) + +hdc.text_color = 0x00FF00 # green +hdc.move_to(250, 200) +hdc.line_to(100, 50) + +hdc.text_color = 0xFF0000 # blue +hdc.move_to(50, 100) +hdc.line_to(200, 250) + +hdc.text_color = 0x00FFFF # yellow +hdc.move_to(250, 100) +hdc.line_to(100, 250) + +hdc.set_clip_rect(clip[0], clip[1], clip[2], clip[3]) + +msg = {} +while upiwin.get_message(msg): + if msg['message'] == upiwin.WM_HWBUTTONUP: + bn = msg['attrs'][0] + if bn == 4: + print("Quitting the application.") + upiwin.post_quit_message(0) diff --git a/scripts/tmp_main.py b/scripts/tmp_main.py new file mode 100644 index 0000000..3fcc94e --- /dev/null +++ b/scripts/tmp_main.py @@ -0,0 +1,64 @@ +# UPIWIN - Micro Pi Windowing Framework Kernel +# Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# ------------------------------------------------------------------------ +# Initial test script +import upiwin +import upiwin_tmp + +def log_touch(event, x, y): + print("Touch {0} at ({1}, {2})".format(event, x, y)) + +upiwin_tmp.filled_rectangle(10, 10, 50, 50, upiwin_tmp.FBPRIMCLR_RED, False) +upiwin_tmp.filled_rectangle(60, 10, 100, 50, upiwin_tmp.FBPRIMCLR_GREEN, False) +upiwin_tmp.filled_rectangle(110, 10, 150, 50, upiwin_tmp.FBPRIMCLR_BLUE, False) +upiwin_tmp.filled_rectangle(10, 60, 50, 100, upiwin_tmp.FBPRIMCLR_CYAN, False) +upiwin_tmp.filled_rectangle(60, 60, 100, 100, upiwin_tmp.FBPRIMCLR_MAGENTA, False) +upiwin_tmp.filled_rectangle(110, 60, 150, 100, upiwin_tmp.FBPRIMCLR_YELLOW, False) +upiwin_tmp.rectangle(10, 110, 150, 150, upiwin_tmp.FBPRIMCLR_WHITE, False) +upiwin_tmp.line(10, 110, 150, 150, upiwin_tmp.FBPRIMCLR_WHITE, False) +upiwin_tmp.line(10, 150, 150, 110, upiwin_tmp.FBPRIMCLR_WHITE, False) + +upiwin_tmp.line(0, 180, 319, 180, upiwin_tmp.FBPRIMCLR_RED, False); +upiwin_tmp.line(0, 196, 319, 196, upiwin_tmp.FBPRIMCLR_RED, False); +upiwin_tmp.textout(10, 180, 'Amy was here!!!') + +msg = {} +while upiwin.get_message(msg): + if msg['message'] == upiwin.WM_HWBUTTONDOWN: + print("Button {0} was pressed.".format(msg['attrs'][0])) + elif msg['message'] == upiwin.WM_HWBUTTONUP: + print("Button {0} was released.".format(msg['attrs'][0])) + elif msg['message'] == upiwin.WM_HWBUTTONCLICK: + print("Button {0} was clicked.".format(msg['attrs'][0])) + bn = msg['attrs'][0] + if bn == 1: + print("Backlight ON.") + upiwin.set_backlight(True) + elif bn == 2: + print("Backlight OFF.") + upiwin.set_backlight(False) + elif bn == 4: + print("Quitting the application.") + upiwin.post_quit_message(0) + elif msg['message'] == upiwin.WM_TOUCHDOWN: + log_touch('DOWN', msg['attrs'][0], msg['attrs'][1]) + elif msg['message'] == upiwin.WM_TOUCHMOVE: + log_touch('MOVE', msg['attrs'][0], msg['attrs'][1]) + elif msg['message'] == upiwin.WM_TOUCHUP: + log_touch('UP', msg['attrs'][0], msg['attrs'][1]) + elif msg['message'] == upiwin.WM_TOUCHCLICK: + log_touch('CLICK', msg['attrs'][0], msg['attrs'][1]) diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..1d581ea --- /dev/null +++ b/src/Makefile @@ -0,0 +1,66 @@ +# UPIWIN - Micro Pi Windowing Framework Kernel +# Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# ------------------------------------------------------------------------ +BUILDUTILS=../buildutils +RESOURCES=../resources +SPLASHSCREEN=splash-vmwcblk.png + +OBJS=main.o sysinput.o ep_init.o ep_upiwin.o ep_backlight.o ep_msg.o ep_graphics.o ep_devctxt.o ep_bitmap.o \ + ep_upiwin_tmp.o ep_util.o fbinit.o rect.o gfxobj.o devctxt.o dc_screen.o fontengine.o \ + bitmap.o stockobj.o fbprimitive.o log.o gpio.o msg_queue.o time_func.o config.o \ + i_freehand.o i_line.o i_rect.o i_fillrect.o i_undo.o i_clear.o splash.o +LIBS=-lpython3.7m -lcrypt -lfreetype -lbcm2835 -lpthread -ldl -lutil -lm +CFLAGS=-I/usr/include/python3.7m -I/usr/include/freetype2 -I/usr/include/libpng16 \ + -Wall -Werror -fstack-protector -fwrapv -fno-PIE -g -O3 -DDEBUG_ASSERT +LDFLAGS=-L/usr/lib/python3.7/config-3.7m-arm-linux-gnueabihf -Xlinker -export-dynamic -Wl,-O1 \ + -Wl,-Bsymbolic-functions + +all: upiwin + +upiwin: $(OBJS) + gcc -o upiwin $(LDFLAGS) $(OBJS) $(LIBS) + +.c.o: + gcc -c $(CFLAGS) $< + +%.o: %.bin + objcopy -I binary -O elf32-littlearm -B arm --rename-section \ + .data=.rodata,alloc,load,readonly,data,contents $< $@ + +splash.bin: $(RESOURCES)/$(SPLASHSCREEN) $(BUILDUTILS)/mkgfx + $(BUILDUTILS)/mkgfx $(RESOURCES)/$(SPLASHSCREEN) splash.bin + +i_freehand.bin: $(RESOURCES)/i_freehand.png $(BUILDUTILS)/mkgfx + $(BUILDUTILS)/mkgfx $(RESOURCES)/i_freehand.png i_freehand.bin + +i_line.bin: $(RESOURCES)/i_line.png $(BUILDUTILS)/mkgfx + $(BUILDUTILS)/mkgfx $(RESOURCES)/i_line.png i_line.bin + +i_rect.bin: $(RESOURCES)/i_rect.png $(BUILDUTILS)/mkgfx + $(BUILDUTILS)/mkgfx $(RESOURCES)/i_rect.png i_rect.bin + +i_fillrect.bin: $(RESOURCES)/i_fillrect.png $(BUILDUTILS)/mkgfx + $(BUILDUTILS)/mkgfx $(RESOURCES)/i_fillrect.png i_fillrect.bin + +i_undo.bin: $(RESOURCES)/i_undo.png $(BUILDUTILS)/mkgfx + $(BUILDUTILS)/mkgfx $(RESOURCES)/i_undo.png i_undo.bin + +i_clear.bin: $(RESOURCES)/i_clear.png $(BUILDUTILS)/mkgfx + $(BUILDUTILS)/mkgfx $(RESOURCES)/i_clear.png i_clear.bin + +clean: + rm -f upiwin *.o splash.bin *~ diff --git a/src/bitmap.c b/src/bitmap.c new file mode 100755 index 0000000..1a62055 --- /dev/null +++ b/src/bitmap.c @@ -0,0 +1,44 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#include +#include "bitmap.h" + +PBITMAP BMP_Create(INT32 width, INT32 height, const void *bits) +{ + PBITMAP rc; + UINT32 tot_size = sizeof(BITMAP) + (width * height * sizeof(UINT16)); + + rc = (PBITMAP)malloc(tot_size); + if (!rc) + return NULL; + memset(rc, 0, tot_size); + _Go_init(&(rc->hdr), BMP_SIG_WORD, tot_size); + rc->width = width; + rc->height = height; + if (bits) + memcpy(rc->bits, bits, width * height * sizeof(UINT16)); + return rc; +} + +void BMP_Delete(PBITMAP pbmp) +{ + Go_release(&(pbmp->hdr)); +} diff --git a/src/bitmap.h b/src/bitmap.h new file mode 100755 index 0000000..a904868 --- /dev/null +++ b/src/bitmap.h @@ -0,0 +1,40 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __BITMAP_H_INCLUDED +#define __BITMAP_H_INCLUDED + +#include "wintype.h" +#include "gfxobj.h" + +#define BMP_SIG_WORD 0x706D4221 /* !Bmp */ + +typedef struct tagBITMAP { + GFXOBJECT hdr; + INT32 width; + INT32 height; + UINT16 bits[0]; +} BITMAP, *PBITMAP; + +extern PBITMAP BMP_Create(INT32 width, INT32 height, const void *bits); +extern void BMP_Delete(PBITMAP pbmp); + +extern PBITMAP _BMP_GetStock(PCSTR name); + +#endif /* __BITMAP_H_INCLUDED */ \ No newline at end of file diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..8199b18 --- /dev/null +++ b/src/config.c @@ -0,0 +1,254 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "scode.h" +#include "log.h" + +/* command line options for UPIWIN */ +static const struct option long_options[] = { + {"framebuffer", required_argument, 0, 'F'}, + {"help", no_argument, 0, 'h'}, + {"touchscreen", required_argument, 0, 'T'}, + { NULL, 0, 0, 0 } +}; + +static const char *short_options = "F:hT:"; + +/* printed to stdout when upiwin is executed with -h/--help option */ +static const char *helptext = + "UPIWIN - Micro Pi Windows server program\n\n" + "Usage: upiwin [options] scriptname [scriptargs]\n\n" + "Available options:\n" + " -F,--framebuffer [devname] - Specifies the framebuffer device name\n" + " -h,--help - Displays this help message.\n" + " -T,--touchscreen - Specifies the touchscreen device name\n" + ""; + +#define EXITFUNCBLOCK_FUNCCOUNT 64 /* number of exit functions per function block */ + +/* exit functions are stored in these data blocks */ +typedef struct tagEXITFUNCBLOCK +{ + struct tagEXITFUNCBLOCK *next; /* chained in single linked list */ + int num_funcs; /* number of functions this block contains */ + PEXITFUNC funcs[EXITFUNCBLOCK_FUNCCOUNT]; /* pointers to functions */ +} EXITFUNCBLOCK, *PEXITFUNCBLOCK; + +/* The global configuration data */ +GLOBAL_CONFIG Gconfig; + +static PEXITFUNCBLOCK exitfuncs = NULL; /* pointer to head of exit function chain */ + +static void run_exit_funcs(void) +{ + int i; + PEXITFUNCBLOCK p; + + while (exitfuncs) + { + p = exitfuncs; + exitfuncs = p->next; + for (i = p->num_funcs - 1; i >= 0; i--) + { + /* execute functions in LIFO order */ + ASSERT(p->funcs[i]); + (*(p->funcs[i]))(); + } + free(p); + } +} + +static void init_defaults(void) +{ + memset(&Gconfig, 0, sizeof(GLOBAL_CONFIG)); + Gconfig.framebuffer_device = "/dev/fb1"; + Gconfig.touchscreen_device = "/dev/input/touchscreen"; + Gconfig.python_loc = "/usr/bin/python3"; + Gconfig.button_debounce = 100; + Gconfig.sys_mq_length = 64; + Gconfig.click_time = 500; + Gconfig.click_radius = 2; +} + +static HRESULT parse_cmdline(int argc, char *argv[], GLOBAL_CONFIG *parsed) +{ + int c; + PSTR pstr; + PPCSTR pargs; + BOOL help = FALSE; + + memset(parsed, 0, sizeof(GLOBAL_CONFIG)); + for (;;) + { + c = getopt_long(argc, argv, short_options, long_options, NULL); + if (c==-1) + break; + switch (c) + { + case 'F': /* frame buffer device name */ + pstr = strdup(optarg); + if (!pstr) + { + Log(LERROR, "Out of memory in parse_cmdline"); + return E_OUTOFMEMORY; + } + if (parsed->framebuffer_device) + free((PVOID)(parsed->framebuffer_device)); + parsed->framebuffer_device = pstr; + break; + + case 'h': /* show help */ + help = TRUE; + break; + + case 'T': /* touchscreen device name */ + pstr = strdup(optarg); + if (!pstr) + { + Log(LERROR, "Out of memory in parse_cmdline"); + return E_OUTOFMEMORY; + } + if (parsed->touchscreen_device) + free((PVOID)(parsed->touchscreen_device)); + parsed->touchscreen_device = pstr; + break; + + default: + fprintf(stderr, "%s: unexpected option -%c\n", argv[0], c); + return E_UNEXPECTED; + } + } + if (help) + { + fputs(helptext, stdout); + return S_FALSE; + } + + if (optind < argc) + { + pstr = realpath(argv[optind], NULL); /* implicit strdup */ + if (!pstr) + { + Log(LERROR, "Out of memory in parse_cmdline"); + return E_OUTOFMEMORY; + } + if (access(pstr, R_OK)) + { + fprintf(stderr, "%s: script %s not found\n", argv[0], pstr); + return UPIWIN_E_INVALIDSCRIPT; + } + parsed->script_name = pstr; + if (++optind < argc) + { + parsed->script_arg_count = argc - optind; + pargs = (PPCSTR)malloc(sizeof(PCSTR) * parsed->script_arg_count); + if (!pargs) + { + Log(LERROR, "Out of memory in parse_cmdline"); + return E_OUTOFMEMORY; + } + for (c = 0; c < parsed->script_arg_count; c++) + { + pargs[c] = strdup(argv[optind++]); + if (!(pargs[c])) + { + Log(LERROR, "Out of memory in parse_cmdline"); + return E_OUTOFMEMORY; + } + } + parsed->script_args = pargs; + } + } + else + { + fprintf(stderr, "%s: no script specified\n", argv[0]); + return UPIWIN_E_NOSCRIPT; + } + + return S_OK; +} + +static void overlay_config(GLOBAL_CONFIG *p) +{ + if (p->framebuffer_device) + Gconfig.framebuffer_device = p->framebuffer_device; + if (p->touchscreen_device) + Gconfig.touchscreen_device = p->touchscreen_device; + /* always overlay the script name and arguments */ + Gconfig.script_name = p->script_name; + Gconfig.script_arg_count = p->script_arg_count; + Gconfig.script_args = p->script_args; +} + +HRESULT Config_setup(int argc, char *argv[]) +{ + HRESULT hr; + GLOBAL_CONFIG from_commandline; + + if (geteuid() != 0) + { + Log(LFATAL, "upiwin must be run with root privileges"); + return E_ACCESSDENIED; + } + + if (atexit(run_exit_funcs)) + { + Log(LFATAL, "Unable to set up exit function mechanism"); + return E_FAIL; + } + + /* set defaults */ + init_defaults(); + + /* evaluate command line */ + hr = parse_cmdline(argc, argv, &from_commandline); + if (hr != S_OK) + return hr; + + /* command line overrides everything */ + overlay_config(&from_commandline); + return S_OK; +} + +HRESULT Config_exitfunc(PEXITFUNC pfn) +{ + PEXITFUNCBLOCK p; + + if (!exitfuncs || (exitfuncs->num_funcs == EXITFUNCBLOCK_FUNCCOUNT)) + { + p = (PEXITFUNCBLOCK)malloc(sizeof(EXITFUNCBLOCK)); + if (!p) + { + Log(LERROR, "unable to allocate another exit function block"); + return E_OUTOFMEMORY; + } + p->next = exitfuncs; + p->num_funcs = 0; + exitfuncs = p; + } + exitfuncs->funcs[exitfuncs->num_funcs++] = pfn; + return S_OK; +} diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..23e45b6 --- /dev/null +++ b/src/config.h @@ -0,0 +1,46 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __CONFIG_H_INCLUDED +#define __CONFIG_H_INCLUDED + +#include "wintype.h" + +typedef void (*PEXITFUNC)(void); + +/* global configuration data for UPIWIN */ +typedef struct tagGLOBAL_CONFIG { + PCSTR framebuffer_device; /* name of frame buffer device */ + PCSTR touchscreen_device; /* name of touchscreen device */ + PCSTR python_loc; /* location of the Python3 executable */ + UINT32 button_debounce; /* minimum time between button up and next button down (ms) */ + UINT32 sys_mq_length; /* length of system message queue */ + UINT32 click_time; /* time between button/touch DOWN and UP to be considered a "click" (ms) */ + UINT32 click_radius; /* maximum number of pixels a touch can "drift" to be considered a "click" */ + PCSTR script_name; /* script name to be run */ + INT32 script_arg_count; /* number of arguments to pass to the script */ + PPCSTR script_args; /* arguments to pass to the script */ +} GLOBAL_CONFIG; + +extern GLOBAL_CONFIG Gconfig; /* one global configuration to rule them all */ + +extern HRESULT Config_setup(int argc, char *argv[]); +extern HRESULT Config_exitfunc(PEXITFUNC pfn); + +#endif /* __CONFIG_H_INCLUDED */ diff --git a/src/dc_screen.c b/src/dc_screen.c new file mode 100755 index 0000000..7ca7790 --- /dev/null +++ b/src/dc_screen.c @@ -0,0 +1,309 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#include +#include "log.h" +#include "fbinit.h" +#include "devctxt.h" +#include "dc_screen.h" +#include "bitmap.h" + +inline static PUINT16 loc_from_coords(PSCREENPRIVDATA priv, INT32 x, INT32 y) +{ + return priv->pdata + (y * priv->pix_per_row) + x; +} + +inline static UINT16 native_from_COLORREF(COLORREF cr) +{ + return (UINT16)(((cr << 8) & 0xF800) | ((cr >> 5) & 0x7E0) | ((cr >> 19) & 0x1F)); +} + +inline static COLORREF COLORREF_from_native(UINT16 cr) +{ + UINT32 tmp = cr; + return (COLORREF)(((tmp << 19) & 0xF80000) | ((tmp << 5) & 0xFC00) | ((tmp >> 8) & 0xF800)); +} + +static inline UINT16 apply_rop2(INT32 op, UINT16 disp, UINT16 pen) +{ + switch (op) + { + case R2_BLACK: + return 0; + case R2_NOTMERGEPEN: + return ~(disp | pen); + case R2_MASKNOTPEN: + return disp & (~pen); + case R2_NOTCOPYPEN: + return ~pen; + case R2_MASKPENNOT: + return (~disp) & pen; + case R2_NOT: + return ~disp; + case R2_XORPEN: + return disp ^ pen; + case R2_NOTMASKPEN: + return ~(disp & pen); + case R2_MASKPEN: + return disp & pen; + case R2_NOTXORPEN: + return ~(disp ^ pen); + case R2_NOP: + return disp; + case R2_MERGENOTPEN: + return disp | (~pen); + case R2_COPYPEN: + return pen; + case R2_MERGEPENNOT: + return (~disp) | pen; + case R2_MERGEPEN: + return disp | pen; + case R2_WHITE: + return (UINT16)(-1); + } + return pen; /* last ditch default */ +} + +static COLORREF screen_set_pixel(PVOID privdata, INT32 x, INT32 y, COLORREF color, INT32 op) +{ + PSCREENPRIVDATA priv = (PSCREENPRIVDATA)privdata; + UINT16 pencolor = native_from_COLORREF(color); + PUINT16 loc = loc_from_coords(priv, x, y); + UINT16 screen = *loc; + *loc = apply_rop2(op, screen, pencolor); + return COLORREF_from_native(screen); +} + +static BOOL screen_line(PVOID privdata, INT32 x1, INT32 y1, INT32 x2, INT32 y2, COLORREF color, INT32 op) +{ + PSCREENPRIVDATA priv = (PSCREENPRIVDATA)privdata; + UINT16 pencolor = native_from_COLORREF(color); + INT32 dx = x2 - x1; + INT32 dy = y2 - y1; + INT32 tmp; + PUINT16 loc; + + ASSERT(x1 >= 0); + ASSERT(x1 < Fb_Info->width); + ASSERT(y1 >= 0); + ASSERT(y1 < Fb_Info->height); + ASSERT(x2 >= 0); + ASSERT(x2 < Fb_Info->width); + ASSERT(y2 >= 0); + ASSERT(y2 < Fb_Info->height); + + /* uses Bresenham's line algorithm with 16-bit fixed-point arithmetic */ + if (ABS(dx) < ABS(dy)) + { + if (y1 > y2) + { + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + dx = -dx; + dy = -dy; + } + loc = loc_from_coords(priv, x1, y1); + tmp = x1; + x1 <<= 16; + dx = (dx << 16) / dy; + while (y1 <= y2) + { + *loc = apply_rop2(op, *loc, pencolor); + x1 += dx; + ++y1; + loc += priv->pix_per_row; + if (tmp != (x1 >> 16)) + { + loc += ((x1 >> 16) - tmp); + tmp = x1 >> 16; + } + } + } + else + { + if (x1 > x2) + { + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + dx = -dx; + dy = -dy; + } + loc = loc_from_coords(priv, x1, y1); + tmp = y1; + y1 <<= 16; + dy = dx ? (dy << 16) / dx : 0; + while (x1 <= x2) + { + *loc = apply_rop2(op, *loc, pencolor); + y1 += dy; + ++x1; + ++loc; + if (tmp != (y1 >> 16)) + { + loc += (((y1 >> 16) - tmp) * priv->pix_per_row); + tmp = y1 >> 16; + } + } + } + return TRUE; +} + +static BOOL screen_solid_rect(PVOID privdata, PRECT rect, COLORREF color, INT32 op) +{ + PSCREENPRIVDATA priv = (PSCREENPRIVDATA)privdata; + UINT16 pencolor = native_from_COLORREF(color); + PUINT16 ps, p; + int y, x; + + ps = loc_from_coords(priv, rect->left, rect->top); + for (y = rect->top; y < rect->bottom; y++) + { + p = ps; + for (x = rect->left; x < rect->right; x++) + { + *p = apply_rop2(op, *p, pencolor); + ++p; + } + ps += priv->pix_per_row; + } + return TRUE; +} + +static const DCFUNTABLE screen_funtable; /* forward declaration */ +static void screen_context_destroy(PVOID obj); + +static PDCTXT screen_create_compat(PVOID privdata) +{ + PSCREENPRIVDATA priv_new; + PBITMAP pbmp; + PDCTXT rc; + + pbmp = BMP_Create(1, 1, NULL); + if (!pbmp) + return NULL; + priv_new = (PSCREENPRIVDATA)malloc(sizeof(SCREENPRIVDATA)); + if (!priv_new) + { + Go_release(&(pbmp->hdr)); + return NULL; + } + priv_new->pix_per_row = pbmp->width; + priv_new->pdata = pbmp->bits; + + rc = _DC_Allocate(&screen_funtable, priv_new); + if (rc) + { + rc->hdr.dtor = screen_context_destroy; + rc->flags = DCFLG_IS_MEMORY; + rc->baserect.left = rc->baserect.top = 0; + rc->baserect.right = pbmp->width; + rc->baserect.bottom = pbmp->height; + memcpy(&(rc->cliprect), &(rc->baserect), sizeof(RECT)); + rc->cur_bitmap = pbmp; + } + else + { + free(priv_new); + Go_release(&(pbmp->hdr)); + } + return rc; +} + +BOOL screen_new_bitmap(PVOID privdata, PBITMAP pbmp) +{ + PSCREENPRIVDATA priv = (PSCREENPRIVDATA)privdata; + priv->pix_per_row = pbmp->width; + priv->pdata = pbmp->bits; + return TRUE; +} + +BOOL screen_bitblt(PVOID p_dest, PRECT r_dest, PVOID p_src, PRECT r_src, UINT32 op) +{ + PSCREENPRIVDATA dest = (PSCREENPRIVDATA)p_dest; + PSCREENPRIVDATA src = (PSCREENPRIVDATA)p_src; + PUINT16 pd, ps; + INT32 width, i; + + pd = loc_from_coords(dest, r_dest->left, r_dest->top); + ps = loc_from_coords(src, r_src->left, r_src->top); + width = r_src->right - r_src->left; + for (i = r_src->top; i < r_src->bottom; ++i) + { + memcpy(pd, ps, width * sizeof(UINT16)); + pd += dest->pix_per_row; + ps += src->pix_per_row; + } + return TRUE; +} + +static const DCFUNTABLE screen_funtable = { + screen_set_pixel, + screen_line, + screen_solid_rect, + screen_create_compat, + screen_new_bitmap, + screen_bitblt +}; + +static void screen_context_destroy(PVOID obj) +{ + PDCTXT pdctxt = (PDCTXT)obj; + _DC_FinalizeCommon(pdctxt); + free(pdctxt->privdata); +} + +PDCTXT DC_CreateScreenContext(void) +{ + PDCTXT rc; + PSCREENPRIVDATA priv; + + priv = (PSCREENPRIVDATA)malloc(sizeof(SCREENPRIVDATA)); + if (!priv) + return NULL; + priv->pix_per_row = Fb_Info->width; + priv->pdata = Fb_Ptr; + + rc = _DC_Allocate(&screen_funtable, priv); + if (rc) + { + rc->hdr.dtor = screen_context_destroy; + rc->flags = DCFLG_IS_SCREEN; + rc->baserect.left = rc->baserect.top = 0; + rc->baserect.right = Fb_Info->width; + rc->baserect.bottom = Fb_Info->height; + memcpy(&(rc->cliprect), &(rc->baserect), sizeof(RECT)); + } + else + free(priv); + return rc; +} + +PDCTXT _DC_CreateScreenCompatibleContext(void) +{ + return screen_create_compat(NULL); +} diff --git a/src/dc_screen.h b/src/dc_screen.h new file mode 100755 index 0000000..575655b --- /dev/null +++ b/src/dc_screen.h @@ -0,0 +1,34 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __DC_SCREEN_H_INCLUDED +#define __DC_SCREEN_H_INCLUDED + +#include "wintype.h" +#include "gfxtype.h" + +typedef struct tagSCREENPRIVDATA { + UINT32 pix_per_row; + UINT16 *pdata; +} SCREENPRIVDATA, *PSCREENPRIVDATA; + +extern PDCTXT DC_CreateScreenContext(void); +extern PDCTXT _DC_CreateScreenCompatibleContext(void); + +#endif /* __DC_SCREEN_H_INCLUDED */ diff --git a/src/devctxt.c b/src/devctxt.c new file mode 100755 index 0000000..7c6ea5d --- /dev/null +++ b/src/devctxt.c @@ -0,0 +1,263 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#include +#include "log.h" +#include "gfxtype.h" +#include "gfxobj.h" +#include "devctxt.h" +#include "bitmap.h" +#include "dc_screen.h" + +inline static BYTE line_clip_outcode(INT32 x, INT32 y, INT32 xmin, INT32 ymin, INT32 xmax, INT32 ymax) +{ + BYTE rc = 0; + if (y < ymin) + rc |= 0x8; + else if (y >= ymax) + rc |= 0x4; + if (x < xmin) + rc |= 0x1; + else if (x >= xmax) + rc |= 0x2; + return rc; +} + +#define CPX 8 /* clipping precision in bits */ + +#define ONE (1 << CPX) /* constant for mathematics */ + +/* these macros keep the number of bits straight when doing fixed-point multiply & divide */ +#define M(a, b) ((((a) * (b))) >> CPX) +#define D(a, b) (((a) << CPX) / (b)) + +static BOOL line_clip(PINT32 output, INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 xmin, INT32 ymin, INT32 xmax, INT32 ymax) +{ + BYTE outcode1, outcode2; + INT32 tmp; + int nloop = 0; + + /* Cohen-Sutherland line-clipping algorithm (see Foley & Van Dam, pp. 145-149) */ + for (;;) + { + if (++nloop == 20) + { + Log(LDEBUG, "POSSIBLE INFINITE LOOP DETECTED - REJECTING"); + return FALSE; + } + outcode1 = line_clip_outcode(x1, y1, xmin, ymin, xmax, ymax); + outcode2 = line_clip_outcode(x2, y2, xmin, ymin, xmax, ymax); + if ((outcode1 & outcode2) != 0) + return FALSE; /* trivial rejection */ + else if ((outcode1 == 0) && (outcode2 == 0)) + break; /* trivial acceptance */ + if (outcode1 == 0) + { + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + outcode1 = outcode2; /* we don't reference outcode2 in the rest of the loop */ + } + if (outcode1 & 0x8) + { + x1 += M(x2 - x1, D(ymin - y1, y2 - y1)); + y1 = ymin; + } + else if (outcode1 & 0x4) + { + x1 += M(x2 - x1, D(ymax - ONE - y1, y2 - y1)); + y1 = ymax - ONE; + } + else if (outcode1 & 0x2) + { + y1 += M(y2 - y1, D(xmax - ONE - x1, x2 - x1)); + x1 = xmax - ONE; + } + else if (outcode1 & 0x1) + { + y1 += M(y2 - y1, D(xmin - x1, x2 - x1)); + x1 = xmin; + } + } + output[0] = x1; + output[1] = y1; + output[2] = x2; + output[3] = y2; + return TRUE; +} + +static BOOL internal_line(PDCTXT pdctxt, INT32 x1, INT32 y1, INT32 x2, INT32 y2) +{ + INT32 buffer[4]; + if (line_clip(buffer, x1 << CPX, y1 << CPX, x2 << CPX, y2 << CPX, pdctxt->cliprect.left << CPX, pdctxt->cliprect.top << CPX, + pdctxt->cliprect.right << CPX, pdctxt->cliprect.bottom << CPX)) + return (*pdctxt->funcs->line)(pdctxt->privdata, buffer[0] >> CPX, buffer[1] >> CPX, buffer[2] >> CPX, buffer[3] >> CPX, pdctxt->color, pdctxt->rop2); + return TRUE; +} + +PDCTXT _DC_Allocate(PDCFUNTABLE funcs, PVOID privdata) +{ + PDCTXT rc = (PDCTXT)malloc(sizeof(DCTXT)); + if (!rc) + return NULL; + memset(rc, 0, sizeof(DCTXT)); + _Go_init(&(rc->hdr), DCTXT_SIG_WORD, sizeof(DCTXT)); + rc->funcs = funcs; + rc->privdata = privdata; + rc->rop2 = R2_COPYPEN; + return rc; +} + +void _DC_FinalizeCommon(PDCTXT pdctxt) +{ + if (pdctxt->cur_bitmap) + Go_release(&(pdctxt->cur_bitmap->hdr)); +} + +COLORREF DC_SetPixel(PDCTXT pdctxt, INT32 x, INT32 y, COLORREF color) +{ + if (!G_coords_in_rect(&(pdctxt->cliprect), x, y)) + return (COLORREF)(-1); + return (*(pdctxt->funcs->set_pixel))(pdctxt->privdata, x, y, color, pdctxt->rop2); +} + +BOOL DC_LineTo(PDCTXT pdctxt, INT32 x, INT32 y) +{ + BOOL rc = internal_line(pdctxt, pdctxt->pos.x, pdctxt->pos.y, x, y); + if (rc) + { + pdctxt->pos.x = x; + pdctxt->pos.y = y; + } + return rc; +} + +BOOL DC_MoveTo(PDCTXT pdctxt, INT32 x, INT32 y, PPOINT oldpt) +{ + if (oldpt) + memcpy(oldpt, &(pdctxt->pos), sizeof(POINT)); + pdctxt->pos.x = x; + pdctxt->pos.y = y; + return TRUE; +} + +BOOL DC_Rectangle(PDCTXT pdctxt, INT32 left, INT32 top, INT32 right, INT32 bottom) +{ + internal_line(pdctxt, left, top, right - 1, top); + internal_line(pdctxt, left, top + 1, left, bottom - 2); + internal_line(pdctxt, right - 1, top + 1, right - 1, bottom - 2); + internal_line(pdctxt, left, bottom - 1, right - 1, bottom - 1); + return TRUE; +} + +BOOL DC_SolidRectangle(PDCTXT pdctxt, INT32 left, INT32 top, INT32 right, INT32 bottom) +{ + RECT rect, actual; + G_set_rect(&rect, left, top, right, bottom); + if (!G_rect_intersect(&actual, &rect, &(pdctxt->cliprect))) + return TRUE; + return (*(pdctxt->funcs->solid_rect))(pdctxt->privdata, &actual, pdctxt->color, pdctxt->rop2); +} + +UINT32 DC_GetROP2(PDCTXT pdctxt) +{ + return pdctxt->rop2; +} + +UINT32 DC_SetROP2(PDCTXT pdctxt, UINT32 rop) +{ + UINT32 rc = pdctxt->rop2; + pdctxt->rop2 = rop; + return rc; +} + +COLORREF DC_GetTextColor(PDCTXT pdctxt) +{ + return pdctxt->color; +} + +COLORREF DC_SetTextColor(PDCTXT pdctxt, COLORREF cr) +{ + COLORREF rc = pdctxt->color; + pdctxt->color = cr; + return rc; +} + +BOOL DC_GetClipRect(PDCTXT pdctxt, PRECT prect) +{ + memcpy(prect, &(pdctxt->cliprect), sizeof(RECT)); + return TRUE; +} + +BOOL DC_SetClipRect(PDCTXT pdctxt, PRECT prect) +{ + memcpy(&(pdctxt->cliprect), prect, sizeof(RECT)); + return TRUE; +} + +PDCTXT DC_CreateCompatible(PDCTXT pdctxt) +{ + if (pdctxt) + return (*(pdctxt->funcs->create_compat))(pdctxt->privdata); + return _DC_CreateScreenCompatibleContext(); +} + +PGFXOBJECT DC_SelectObject(PDCTXT pdctxt, PGFXOBJECT pobj) +{ + if (pobj->sig == BMP_SIG_WORD) + { + if ((pdctxt->flags & DCFLG_TYPES) == DCFLG_IS_MEMORY) + { + RECT rtmp; + PBITMAP rbmp = pdctxt->cur_bitmap; + Go_addref(pobj); + if ((*(pdctxt->funcs->new_bitmap))(pdctxt->privdata, (PBITMAP)pobj)) + { + pdctxt->cur_bitmap = (PBITMAP)pobj; + pdctxt->baserect.left = pdctxt->baserect.top = 0; + pdctxt->baserect.right = ((PBITMAP)pobj)->width; + pdctxt->baserect.bottom = ((PBITMAP)pobj)->height; + G_rect_intersect(&rtmp, &(pdctxt->baserect), &(pdctxt->cliprect)); + memcpy(&(pdctxt->cliprect), &rtmp, sizeof(RECT)); + return (PGFXOBJECT)rbmp; + } + Go_release(pobj); + } + } + return NULL; +} + +BOOL DC_BitBlt(PDCTXT dest, INT32 x, INT32 y, INT32 width, INT32 height, PDCTXT source, INT32 x1, INT32 y1, UINT32 rop) +{ + RECT destrect, actualdest, srcrect, actualsrc; + + G_set_rect(&destrect, x, y, x + width, y + height); + if (!G_rect_intersect(&actualdest, &destrect, &(dest->cliprect))) + return TRUE; /* no-op */ + G_set_rect(&srcrect, x1, y1, x1 + (actualdest.right - actualdest.left), y1 + (actualdest.bottom - actualdest.top)); + if (!G_rect_intersect(&actualsrc, &srcrect, &(source->baserect))) + return TRUE; + actualdest.right = actualdest.left + (actualsrc.right - actualsrc.left); + actualdest.bottom = actualdest.top + (actualsrc.bottom - actualsrc.top); + return (*(dest->funcs->bitblt))(dest->privdata, &actualdest, source->privdata, &actualsrc, rop); +} diff --git a/src/devctxt.h b/src/devctxt.h new file mode 100755 index 0000000..f714c66 --- /dev/null +++ b/src/devctxt.h @@ -0,0 +1,106 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __DEVCTXT_H_INCLUDED +#define __DEVCTXT_H_INCLUDED + +#include "wintype.h" +#include "gfxtype.h" +#include "gfxobj.h" +#include "bitmap.h" + +#define DCTXT_SIG_WORD 0x78744344 /* "DCtx */ + +/* Raster operation codes */ +#define R2_BLACK 1 +#define R2_NOTMERGEPEN 2 +#define R2_MASKNOTPEN 3 +#define R2_NOTCOPYPEN 4 +#define R2_MASKPENNOT 5 +#define R2_NOT 6 +#define R2_XORPEN 7 +#define R2_NOTMASKPEN 8 +#define R2_MASKPEN 9 +#define R2_NOTXORPEN 10 +#define R2_NOP 11 +#define R2_MERGENOTPEN 12 +#define R2_COPYPEN 13 +#define R2_MERGEPENNOT 14 +#define R2_MERGEPEN 15 +#define R2_WHITE 16 + +struct tagDCTXT; /* forward declaration */ + +typedef COLORREF (*DCtx_SetPixel)(PVOID privdata, INT32 x, INT32 y, COLORREF color, INT32 op); +typedef BOOL (*DCtx_Line)(PVOID privdata, INT32 x1, INT32 y1, INT32 x2, INT32 y2, COLORREF color, INT32 op); +typedef BOOL (*DCtx_SolidRect)(PVOID privdata, PRECT rect, COLORREF color, INT32 op); +typedef struct tagDCTXT *(*DCtx_CreateCompat)(PVOID privdata); +typedef BOOL (*DCtx_NewBitmap)(PVOID privdata, PBITMAP pbmp); +typedef BOOL (*DCtx_BitBlt)(PVOID p_dest, PRECT r_dest, PVOID p_src, PRECT r_src, UINT32 op); + +typedef struct tagDCFUNTABLE { + DCtx_SetPixel set_pixel; /* sets a single pixel on the display */ + DCtx_Line line; /* draws a line on the display */ + DCtx_SolidRect solid_rect; /* draws a solid rectangle on the display */ + DCtx_CreateCompat create_compat; /* create a memory DC compatible with this one */ + DCtx_NewBitmap new_bitmap; /* new bitmap selected notification */ + DCtx_BitBlt bitblt; /* bit block transfer */ +} DCFUNTABLE; + +typedef const DCFUNTABLE *PDCFUNTABLE; + +typedef struct tagDCTXT { + GFXOBJECT hdr; /* the header of all objects */ + PDCFUNTABLE funcs; /* device context functions */ + PVOID privdata; /* private data for the type of DC */ + UINT32 flags; /* flags for the DC */ + RECT baserect; /* base rectangle */ + RECT cliprect; /* clipping rectangle */ + POINT pos; /* current position */ + UINT32 rop2; /* current raster operation */ + COLORREF color; /* current drawing color (XXX replace with pens later) */ + PBITMAP cur_bitmap; /* current selected bitmap */ +} DCTXT, *PDCTXT; + +#define DCFLG_TYPES 0x03 +#define DCFLG_IS_SCREEN 0x00 +#define DCFLG_IS_MEMORY 0x01 + +extern PDCTXT _DC_Allocate(PDCFUNTABLE funcs, PVOID privdata); +extern void _DC_FinalizeCommon(PDCTXT pdctxt); + +extern COLORREF DC_SetPixel(PDCTXT pdctxt, INT32 x, INT32 y, COLORREF color); +extern BOOL DC_LineTo(PDCTXT pdctxt, INT32 x, INT32 y); +extern BOOL DC_MoveTo(PDCTXT pdctxt, INT32 x, INT32 y, PPOINT oldpt); +extern BOOL DC_Rectangle(PDCTXT pdctxt, INT32 left, INT32 top, INT32 right, INT32 bottom); +extern BOOL DC_SolidRectangle(PDCTXT pdctxt, INT32 left, INT32 top, INT32 right, INT32 bottom); +extern UINT32 DC_GetROP2(PDCTXT pdctxt); +extern UINT32 DC_SetROP2(PDCTXT pdctxt, UINT32 rop); +extern COLORREF DC_GetTextColor(PDCTXT pdctxt); +extern COLORREF DC_SetTextColor(PDCTXT pdctxt, COLORREF cr); +extern BOOL DC_GetClipRect(PDCTXT pdctxt, PRECT prect); +extern BOOL DC_SetClipRect(PDCTXT pdctxt, PRECT prect); +extern PDCTXT DC_CreateCompatible(PDCTXT pdctxt); +extern PGFXOBJECT DC_SelectObject(PDCTXT pdctxt, PGFXOBJECT pobj); +extern BOOL DC_BitBlt(PDCTXT dest, INT32 x, INT32 y, INT32 width, INT32 height, PDCTXT source, INT32 x1, INT32 y1, UINT32 rop); + +#define DC_addref(pdctxt) Go_addref(&(pdctxt->hdr)) +#define DC_release(pdctxt) Go_release(&(pdctxt->hdr)) + +#endif /* __DEVCTXT_H_INCLUDED */ diff --git a/src/ep_backlight.c b/src/ep_backlight.c new file mode 100644 index 0000000..188294f --- /dev/null +++ b/src/ep_backlight.c @@ -0,0 +1,84 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#define PY_SSIZE_T_CLEAN +#include +#include "scode.h" +#include "log.h" +#include "gpio.h" +#include "ep_upiwin.h" +#include "ep_init.h" + +PyObject *Epython_get_backlight(PyObject *self, PyObject *args) +{ + PUPIWIN_STATE pstate; + + if (!PyArg_ParseTuple(args, "")) + return NULL; + pstate = (PUPIWIN_STATE)PyModule_GetState(UPIWIN_module); + return PyBool_FromLong((long)(pstate->backlight_on)); +} + +PyObject *Epython_set_backlight(PyObject *self, PyObject *args) +{ + PUPIWIN_STATE pstate; + int new_state; + + if (!PyArg_ParseTuple(args, "p", &new_state)) + return NULL; + pstate = (PUPIWIN_STATE)PyModule_GetState(UPIWIN_module); + if (new_state && !(pstate->backlight_on)) + Gpio_set_backlight(pstate->backlight_level); + else if (!new_state && pstate->backlight_on) + Gpio_set_backlight(0); + pstate->backlight_on = MAKEBOOL(new_state); + return PyLong_FromUnsignedLong(S_OK); +} + +PyObject *Epython_get_backlight_level(PyObject *self, PyObject *args) +{ + PUPIWIN_STATE pstate; + + if (!PyArg_ParseTuple(args, "")) + return NULL; + pstate = (PUPIWIN_STATE)PyModule_GetState(UPIWIN_module); + return PyLong_FromUnsignedLong(pstate->backlight_level); +} + +PyObject *Epython_set_backlight_level(PyObject *self, PyObject *args) +{ + PUPIWIN_STATE pstate; + UINT32 new_level; + HRESULT hr = S_OK; + + if (!PyArg_ParseTuple(args, "k", &new_level)) + return NULL; + if (new_level <= GSB_BACKLIGHT_MAX) + { + pstate = (PUPIWIN_STATE)PyModule_GetState(UPIWIN_module); + if (pstate->backlight_on) + Gpio_set_backlight(new_level); + pstate->backlight_level = new_level; + } + else + { + hr = E_INVALIDARG; + } + return PyLong_FromUnsignedLong(hr); +} diff --git a/src/ep_bitmap.c b/src/ep_bitmap.c new file mode 100755 index 0000000..89e70e0 --- /dev/null +++ b/src/ep_bitmap.c @@ -0,0 +1,154 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#define PY_SSIZE_T_CLEAN +#include +#include "scode.h" +#include "log.h" +#include "gfxobj.h" +#include "bitmap.h" +#include "ep_types.h" + +static PyMethodDef BitmapMethods[] = { + {NULL, NULL, 0, NULL} +}; + +static PyObject *bitmap_get_width(BitmapObject *self, void *closure) +{ + if (!(self->pbmp)) + { + PyErr_SetString(PyExc_RuntimeError, "bad bitmap object"); + return NULL; + } + return PyLong_FromUnsignedLong(self->pbmp->width); +} + +static PyObject *bitmap_get_height(BitmapObject *self, void *closure) +{ + if (!(self->pbmp)) + { + PyErr_SetString(PyExc_RuntimeError, "bad bitmap object"); + return NULL; + } + return PyLong_FromUnsignedLong(self->pbmp->height); +} + +static PyGetSetDef BitmapProperties[] = { + {"width", (getter)bitmap_get_width, NULL, + "Width of this bitmap", NULL}, + {"height", (getter)bitmap_get_height, NULL, + "Height of this bitmap", NULL}, + {NULL, NULL, NULL, NULL, NULL} +}; + +static int bitmap_init(BitmapObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = { "stock", "width", "height", NULL }; + const char *stock; + int width = 0, height = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|$sii", kwlist, &stock, &width, &height)) + return -1; + + if (stock) + { + self->pbmp = _BMP_GetStock(stock); + if (!(self->pbmp)) + { + PyErr_Format(PyExc_RuntimeError, "no such stock bitmap: '%s'", stock); + return -1; + } + } + else + { + width = MAX(1, width); + height = MAX(1, height); + self->pbmp = BMP_Create(width, height, NULL); + if (!(self->pbmp)) + { + PyErr_SetString(PyExc_RuntimeError, "unable to create bitmap"); + return -1; + } + } + return 0; +} + +static void bitmap_dealloc(BitmapObject *self) +{ + if (self->pbmp) + BMP_Delete(self->pbmp); + Py_TYPE(self)->tp_free((PyObject *)self); +} + +PyTypeObject BitmapType = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "upiwin.Bitmap", + .tp_doc = "Bitmap object", + .tp_basicsize = sizeof(BitmapObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = PyType_GenericNew, + .tp_init = (initproc)bitmap_init, + .tp_dealloc = (destructor)bitmap_dealloc, + .tp_methods = BitmapMethods, + .tp_getset = BitmapProperties, +}; + +HRESULT Epython_register_bitmap(PyObject *module) +{ + if (PyType_Ready(&BitmapType) < 0) + return E_FAIL; + Py_INCREF(&BitmapType); + if (PyModule_AddObject(module, "Bitmap", (PyObject *)(&BitmapType)) < 0) + { + Py_DECREF(&BitmapType); + return E_FAIL; + } + return S_OK; +} + +PyObject *Epython_wrap_bitmap(PBITMAP pbmp) +{ + PyObject *rc = NULL, *args, *kwargs; + BitmapObject *pbitmapobj; + + args = PyTuple_New(0); + if (args) + { + kwargs = PyDict_New(); + if (kwargs) + { + rc = PyType_GenericNew(&BitmapType, args, kwargs); + if (rc) + { + pbitmapobj = (BitmapObject *)rc; + if (pbitmapobj->pbmp) + BMP_Delete(pbitmapobj->pbmp); + pbitmapobj->pbmp = pbmp; + } + Py_DECREF(kwargs); + } + Py_DECREF(args); + } + + if (!rc) + PyErr_SetString(PyExc_RuntimeError, "unable to create bitmap"); + return rc; +} diff --git a/src/ep_devctxt.c b/src/ep_devctxt.c new file mode 100755 index 0000000..bc58dcd --- /dev/null +++ b/src/ep_devctxt.c @@ -0,0 +1,370 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#define PY_SSIZE_T_CLEAN +#include +#include "wintype.h" +#include "scode.h" +#include "log.h" +#include "devctxt.h" +#include "dc_screen.h" +#include "ep_init.h" +#include "ep_types.h" + +static PyObject *devctxt_set_pixel(DevCtxtObject *self, PyObject *args) +{ + INT32 x, y; + COLORREF color, rc; + + if (!PyArg_ParseTuple(args, "iik", &x, &y, &color)) + return NULL; + if (!(self->pdctxt)) + { + PyErr_SetString(PyExc_RuntimeError, "bad device context"); + return NULL; + } + rc = DC_SetPixel(self->pdctxt, x, y, color); + return PyLong_FromUnsignedLong(rc); +} + +static PyObject *devctxt_line_to(DevCtxtObject *self, PyObject *args) +{ + INT32 x, y; + BOOL rc; + + if (!PyArg_ParseTuple(args, "ii", &x, &y)) + return NULL; + if (!(self->pdctxt)) + { + PyErr_SetString(PyExc_RuntimeError, "bad device context"); + return NULL; + } + rc = DC_LineTo(self->pdctxt, x, y); + return PyBool_FromLong(rc); +} + +static PyObject *devctxt_move_to(DevCtxtObject *self, PyObject *args) +{ + INT32 x, y; + BOOL rc; + + if (!PyArg_ParseTuple(args, "ii", &x, &y)) + return NULL; + if (!(self->pdctxt)) + { + PyErr_SetString(PyExc_RuntimeError, "bad device context"); + return NULL; + } + rc = DC_MoveTo(self->pdctxt, x, y, NULL); + return PyBool_FromLong(rc); +} + +static PyObject *devctxt_rectangle(DevCtxtObject *self, PyObject *args) +{ + INT32 left, top, right, bottom; + BOOL rc; + + if (!PyArg_ParseTuple(args, "iiii", &left, &top, &right, &bottom)) + return NULL; + if (!(self->pdctxt)) + { + PyErr_SetString(PyExc_RuntimeError, "bad device context"); + return NULL; + } + rc = DC_Rectangle(self->pdctxt, left, top, right, bottom); + return PyBool_FromLong(rc); +} + +static PyObject *devctxt_solid_rectangle(DevCtxtObject *self, PyObject *args) +{ + INT32 left, top, right, bottom; + BOOL rc; + + if (!PyArg_ParseTuple(args, "iiii", &left, &top, &right, &bottom)) + return NULL; + if (!(self->pdctxt)) + { + PyErr_SetString(PyExc_RuntimeError, "bad device context"); + return NULL; + } + rc = DC_SolidRectangle(self->pdctxt, left, top, right, bottom); + return PyBool_FromLong(rc); +} + +static PyObject *devctxt_bitblt(DevCtxtObject *self, PyObject *args) +{ + INT32 x, y, width, height, x1, y1; + UINT32 rop; + DevCtxtObject *source; + BOOL rc; + + if (!PyArg_ParseTuple(args, "iiiiO!iik", &x, &y, &width, &height, &DevCtxtType, &source, &x1, &y1, &rop)) + return NULL; + if (!(self->pdctxt) || !(source->pdctxt)) + { + PyErr_SetString(PyExc_RuntimeError, "bad device context"); + return NULL; + } + + rc = DC_BitBlt(self->pdctxt, x, y, width, height, source->pdctxt, x1, y1, rop); + return PyBool_FromLong(rc); +} + +static PyObject *devctxt_get_clip_rect(DevCtxtObject *self, PyObject *args) +{ + RECT rect; + + if (!PyArg_ParseTuple(args, "")) + return NULL; + if (!(self->pdctxt)) + { + PyErr_SetString(PyExc_RuntimeError, "bad device context"); + return NULL; + } + DC_GetClipRect(self->pdctxt, &rect); + return Py_BuildValue("(i,i,i,i)", rect.left, rect.top, rect.right, rect.bottom); +} + +static PyObject *devctxt_set_clip_rect(DevCtxtObject *self, PyObject *args) +{ + RECT rect; + BOOL rc; + + if (!PyArg_ParseTuple(args, "iiii", &(rect.left), &(rect.top), &(rect.right), &(rect.bottom))) + return NULL; + if (!(self->pdctxt)) + { + PyErr_SetString(PyExc_RuntimeError, "bad device context"); + return NULL; + } + rc = DC_SetClipRect(self->pdctxt, &rect); + return PyBool_FromLong(rc); +} + +static PyObject *devctxt_select_bitmap(DevCtxtObject *self, BitmapObject *newbmp) +{ + BitmapObject *old_bitmap = NULL; + PBITMAP old_pbmp; + + if ((self->pdctxt->flags & DCFLG_TYPES) != DCFLG_IS_MEMORY) + { + PyErr_SetString(PyExc_RuntimeError, "must select bitmap into memory device context"); + return NULL; + } + old_bitmap = self->selected_bitmap; + old_pbmp = (PBITMAP)DC_SelectObject(self->pdctxt, (PGFXOBJECT)(newbmp->pbmp)); + if (!old_bitmap) + { + old_bitmap = (BitmapObject *)Epython_wrap_bitmap(old_pbmp); + if (!old_bitmap) + { + DC_SelectObject(self->pdctxt, (PGFXOBJECT)old_pbmp); + return NULL; + } + else + { + Py_INCREF(old_bitmap); + self->selected_bitmap = old_bitmap; + } + } + ASSERT(old_bitmap); + ASSERT(self->selected_bitmap); + ASSERT(newbmp); + Py_DECREF(self->selected_bitmap); + self->selected_bitmap = newbmp; + Py_INCREF(self->selected_bitmap); + return (PyObject *)old_bitmap; +} + +static PyObject *devctxt_select_object(DevCtxtObject *self, PyObject *args) +{ + PyObject *obj; + + if (!PyArg_ParseTuple(args, "O", &obj)) + return NULL; + if (!obj) + { + PyErr_SetString(PyExc_RuntimeError, "bad object selected"); + return NULL; + } + if (PyObject_TypeCheck(obj, &BitmapType)) + return devctxt_select_bitmap(self, (BitmapObject *)obj); + PyErr_SetString(PyExc_RuntimeError, "unknown type of object selected"); + return NULL; +} + +static PyMethodDef DevCtxtMethods[] = { + {"set_pixel", (PyCFunction)devctxt_set_pixel, METH_VARARGS, + "Sets a single pixel on the display."}, + {"line_to", (PyCFunction)devctxt_line_to, METH_VARARGS, + "Draws a line from the current position to the specified location."}, + {"move_to", (PyCFunction)devctxt_move_to, METH_VARARGS, + "Draws a line from the current position to the specified location."}, + {"rectangle", (PyCFunction)devctxt_rectangle, METH_VARARGS, + "Draws a rectangle."}, + {"solid_rectangle", (PyCFunction)devctxt_solid_rectangle, METH_VARARGS, + "Draws a solid rectangle."}, + {"bitblt", (PyCFunction)devctxt_bitblt, METH_VARARGS, + "Copy bits from one device context to another."}, + {"select_object", (PyCFunction)devctxt_select_object, METH_VARARGS, + "Selects a graphic object into the device context."}, + {"get_clip_rect", (PyCFunction)devctxt_get_clip_rect, METH_VARARGS, + "Returns the current clipping rectangle of the device context."}, + {"set_clip_rect", (PyCFunction)devctxt_set_clip_rect, METH_VARARGS, + "Sets the current clipping rectangle of the device context."}, + {NULL, NULL, 0, NULL} +}; + +static PyObject *devctxt_get_rop2(DevCtxtObject *self, void *closure) +{ + if (!(self->pdctxt)) + { + PyErr_SetString(PyExc_RuntimeError, "bad device context"); + return NULL; + } + return PyLong_FromUnsignedLong(DC_GetROP2(self->pdctxt)); +} + +static int devctxt_set_rop2(DevCtxtObject *self, PyObject *value, void *closure) +{ + UINT32 v; + + if (!(self->pdctxt)) + { + PyErr_SetString(PyExc_RuntimeError, "bad device context"); + return -1; + } + if (value == NULL) + { + PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute"); + return -1; + } + v = PyLong_AsUnsignedLong(value); + if (PyErr_Occurred()) + return -1; + DC_SetROP2(self->pdctxt, v); + return 0; +} + +static PyObject *devctxt_get_text_color(DevCtxtObject *self, void *closure) +{ + if (!(self->pdctxt)) + { + PyErr_SetString(PyExc_RuntimeError, "bad device context"); + return NULL; + } + return PyLong_FromUnsignedLong(DC_GetTextColor(self->pdctxt)); +} + +static int devctxt_set_text_color(DevCtxtObject *self, PyObject *value, void *closure) +{ + COLORREF v; + + if (!(self->pdctxt)) + { + PyErr_SetString(PyExc_RuntimeError, "bad device context"); + return -1; + } + if (value == NULL) + { + PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute"); + return -1; + } + v = PyLong_AsUnsignedLong(value); + if (PyErr_Occurred()) + return -1; + DC_SetTextColor(self->pdctxt, v); + return 0; +} + +static PyGetSetDef DevCtxtProperties[] = { + {"rop2", (getter)devctxt_get_rop2, (setter)devctxt_set_rop2, + "Current raster operation", NULL}, + {"text_color", (getter)devctxt_get_text_color, (setter)devctxt_set_text_color, + "Current text color", NULL}, + {NULL, NULL, NULL, NULL, NULL} +}; + +static void devctxt_dealloc(DevCtxtObject *self) +{ + if (self->pdctxt) + DC_release(self->pdctxt); + Py_TYPE(self)->tp_free((PyObject *)self); +} + +static int devctxt_init(DevCtxtObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = { "type", NULL }; + const char *type; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "$s", kwlist, &type)) + return -1; + if (strcmp(type, "screen") == 0) + { + self->pdctxt = DC_CreateScreenContext(); + if (!(self->pdctxt)) + { + PyErr_SetString(PyExc_RuntimeError, "unable to create screen context"); + return -1; + } + } + else if (strcmp(type, "memory") == 0) + { + self->pdctxt = _DC_CreateScreenCompatibleContext(); + if (!(self->pdctxt)) + { + PyErr_SetString(PyExc_RuntimeError, "unable to create memory context"); + return -1; + } + } + else + { + PyErr_Format(PyExc_RuntimeError, "invalid type '%s'", type); + return -1; + } + return 0; +} + +PyTypeObject DevCtxtType = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "upiwin.DevCtxt", + .tp_doc = "Device context object", + .tp_basicsize = sizeof(DevCtxtObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = PyType_GenericNew, + .tp_init = (initproc)devctxt_init, + .tp_dealloc = (destructor)devctxt_dealloc, + .tp_methods = DevCtxtMethods, + .tp_getset = DevCtxtProperties, +}; + +HRESULT Epython_register_devctxt(PyObject *module) +{ + if (PyType_Ready(&DevCtxtType) < 0) + return E_FAIL; + Py_INCREF(&DevCtxtType); + if (PyModule_AddObject(module, "DevCtxt", (PyObject *)(&DevCtxtType)) < 0) + { + Py_DECREF(&DevCtxtType); + return E_FAIL; + } + return S_OK; +} diff --git a/src/ep_graphics.c b/src/ep_graphics.c new file mode 100755 index 0000000..a029b08 --- /dev/null +++ b/src/ep_graphics.c @@ -0,0 +1,32 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#define PY_SSIZE_T_CLEAN +#include +#include "wintype.h" +#include "gfxtype.h" + +PyObject *Epython_rgb(PyObject *self, PyObject *args) +{ + UINT32 r, g, b; + + if (!PyArg_ParseTuple(args, "kkk", &r, &g, &b)) + return NULL; + return PyLong_FromUnsignedLong(RGB(r, g, b)); +} diff --git a/src/ep_init.c b/src/ep_init.c new file mode 100644 index 0000000..9e23517 --- /dev/null +++ b/src/ep_init.c @@ -0,0 +1,165 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#include +#include +#define PY_SSIZE_T_CLEAN +#include +#include "scode.h" +#include "config.h" +#include "log.h" +#include "ep_init.h" +#include "ep_util.h" + +static wchar_t *python_name = NULL; /* location of the Python executable */ + +PyObject *UPIWIN_module = NULL; +PyObject *UPIWIN_tmp_module = NULL; + +/* used to link the two modules into Python's init table */ +static struct _inittab upiwin_inittab[] = { + { MOD_NAME_UPIWIN, Epython_init_upiwin_module }, + { MOD_NAME_UPIWIN_TMP, Epython_init_upiwin_tmp_module }, + { NULL, NULL } +}; + +static void epython_cleanup(void) +{ + Py_DECREF(UPIWIN_tmp_module); + UPIWIN_tmp_module = NULL; + Py_DECREF(UPIWIN_module); + UPIWIN_module = NULL; + Py_FinalizeEx(); + PyMem_RawFree(python_name); + python_name = NULL; +} + +HRESULT Epython_setup(void) +{ + HRESULT hr; + size_t size; + + python_name = Py_DecodeLocale(Gconfig.python_loc, &size); + if (!python_name) + { + if (size==(size_t)(-1)) + { + Log(LFATAL, "error allocating Python program location"); + return E_OUTOFMEMORY; + } + else + { + Log(LFATAL, "internal error in Py_DecodeLocale"); + return E_UNEXPECTED; + } + } + Py_SetProgramName(python_name); + + if (PyImport_ExtendInittab(upiwin_inittab)) + { + Log(LFATAL, "error allocating extended init table"); + hr = E_OUTOFMEMORY; + goto error_0; + } + + Py_Initialize(); + + /* Import the modules */ + UPIWIN_module = PyImport_ImportModule(MOD_NAME_UPIWIN); + if (!UPIWIN_module) + { + Log(LFATAL, "error importing the upiwin module"); + hr = Epython_trace_exception(); + goto error_1; + } + UPIWIN_tmp_module = PyImport_ImportModule(MOD_NAME_UPIWIN_TMP); + if (!UPIWIN_tmp_module) + { + Log(LFATAL, "error importing the upiwin_tmp module"); + hr = Epython_trace_exception(); + goto error_2; + } + + hr = Config_exitfunc(epython_cleanup); + if (FAILED(hr)) + epython_cleanup(); + return hr; + +error_2: + Py_DECREF(UPIWIN_module); + UPIWIN_module = NULL; +error_1: + Py_FinalizeEx(); +error_0: + PyMem_RawFree(python_name); + python_name = NULL; + return hr; +} + +HRESULT Epython_run(void) +{ + HRESULT hr = S_OK; + int i; + FILE *fp; + wchar_t **args; + + Log(LINFO, "Ready to execute %s", Gconfig.script_name); + fp = fopen(Gconfig.script_name, "rb"); + if (fp) + { + args = (wchar_t **)alloca((Gconfig.script_arg_count + 1) * sizeof(wchar_t *)); + memset(args, 0, (Gconfig.script_arg_count + 1) * sizeof(wchar_t *)); + args[0] = Py_DecodeLocale(Gconfig.script_name, NULL); + if (args[0]) + { + for (i=0; i +#include "wintype.h" + +#define MOD_NAME_UPIWIN "upiwin" +#define MOD_NAME_UPIWIN_TMP "upiwin_tmp" + +extern PyObject *UPIWIN_module; +extern PyObject *UPIWIN_tmp_module; + +extern PyObject *Epython_init_upiwin_module(void); +extern PyObject *Epython_init_upiwin_tmp_module(void); + +extern HRESULT Epython_register_devctxt(PyObject *module); +extern HRESULT Epython_register_bitmap(PyObject *module); + +extern HRESULT Epython_setup(void); +extern HRESULT Epython_run(void); + +#endif /* __EP_INIT_H_INCLUDED */ diff --git a/src/ep_msg.c b/src/ep_msg.c new file mode 100755 index 0000000..c2fbca5 --- /dev/null +++ b/src/ep_msg.c @@ -0,0 +1,90 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#define PY_SSIZE_T_CLEAN +#include +#include "scode.h" +#include "log.h" +#include "msg_queue.h" +#include "sysinput.h" +#include "ep_upiwin.h" +#include "ep_init.h" + +static HRESULT convert_msg(PyObject *target, PMSG source) +{ + PyObject *attr; + + ASSERT(PyDict_CheckExact(target)); + PyDict_Clear(target); + attr = PyLong_FromUnsignedLong(source->target); + if (!attr) + return E_FAIL; + if (PyDict_SetItemString(target, "target", attr)) + return E_FAIL; + attr = PyLong_FromUnsignedLong(source->message); + if (!attr) + return E_FAIL; + if (PyDict_SetItemString(target, "message", attr)) + return E_FAIL; + attr = Py_BuildValue("[k,k]", source->attrs[0], source->attrs[1]); + if (!attr) + return E_FAIL; + if (PyDict_SetItemString(target, "attrs", attr)) + return E_FAIL; + attr = PyLong_FromUnsignedLongLong(source->timestamp); + if (!attr) + return E_FAIL; + if (PyDict_SetItemString(target, "timestamp", attr)) + return E_FAIL; + return S_OK; +} + +PyObject *Epython_get_message(PyObject *self, PyObject *args) +{ + PyObject *out; + MSG msg; + + if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &out)) + return NULL; + + /* release the GIL to allow us to block waiting for input if necessary */ + Py_BEGIN_ALLOW_THREADS + while (!Mq_peek(Sys_Queue, &msg, PEEK_REMOVE)) + Sys_wait_for_input(); + Py_END_ALLOW_THREADS + + if (FAILED(convert_msg(out, &msg))) + { + PyErr_SetString(PyExc_RuntimeError, "could not convert received message"); + return NULL; + } + return PyBool_FromLong(msg.message != WM_QUIT); +} + +PyObject *Epython_post_quit_message(PyObject *self, PyObject *args) +{ + INT32 exitcode; + + if (!PyArg_ParseTuple(args, "i", &exitcode)) + return NULL; + Sys_Exit_Code = exitcode; + Mq_post1(Sys_Queue, 0, WM_QUIT, exitcode); + Py_RETURN_NONE; +} + diff --git a/src/ep_types.h b/src/ep_types.h new file mode 100755 index 0000000..751cc5a --- /dev/null +++ b/src/ep_types.h @@ -0,0 +1,47 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __EP_TYPES_H_INCLUDED +#define __EP_TYPES_H_INCLUDED + +#define PY_SSIZE_T_CLEAN +#include +#include "wintype.h" +#include "gfxtype.h" +#include "gfxobj.h" +#include "devctxt.h" +#include "bitmap.h" + +typedef struct tagBitmapObject { + PyObject_HEAD + PBITMAP pbmp; +} BitmapObject; + +typedef struct tagDevCtxtObject { + PyObject_HEAD + PDCTXT pdctxt; + BitmapObject *selected_bitmap; +} DevCtxtObject; + +extern PyTypeObject DevCtxtType; +extern PyTypeObject BitmapType; + +extern PyObject *Epython_wrap_bitmap(PBITMAP pbmp); + +#endif /* __EP_TYPES_H_INCLUDED */ diff --git a/src/ep_upiwin.c b/src/ep_upiwin.c new file mode 100644 index 0000000..91a418a --- /dev/null +++ b/src/ep_upiwin.c @@ -0,0 +1,126 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#define PY_SSIZE_T_CLEAN +#include +#include "scode.h" +#include "msg.h" +#include "gpio.h" +#include "ep_init.h" +#include "ep_upiwin.h" +#include "ep_util.h" +#include "devctxt.h" + +static PyMethodDef UPIWINMethods[] = { + /* Backlight control functions */ + {"get_backlight", Epython_get_backlight, METH_VARARGS, + "Returns the current status of the backlight (True=on, False=off)."}, + {"set_backlight", Epython_set_backlight, METH_VARARGS, + "Sets the current status of the backlight (True=on, False=off). Returns a SCODE."}, + {"get_backlight_level", Epython_get_backlight_level, METH_VARARGS, + "Returns the current intensity level of the backlight."}, + {"set_backlight_level", Epython_set_backlight_level, METH_VARARGS, + "Sets the current intensity level of the backlight. Returns a SCODE."}, + /* Message functions */ + {"get_message", Epython_get_message, METH_VARARGS, + "Retrieves a message from the message queue, blocking if necessary."}, + {"post_quit_message", Epython_post_quit_message, METH_VARARGS, + "Posts a WM_QUIT message to the message queue, with an exit code."}, + /* Graphics functions */ + {"rgb", Epython_rgb, METH_VARARGS, + "Creates a color value from separate red, green, and blue indexes."}, + {NULL, NULL, 0, NULL} +}; + +static PyModuleDef DefUPIWIN = { + PyModuleDef_HEAD_INIT, /* standard garbage */ + MOD_NAME_UPIWIN, /* module name */ + NULL, /* no doc string */ + sizeof(UPIWIN_STATE), /* per-module memory */ + UPIWINMethods, /* method defs */ + NULL, /* no slots for multi-phase init */ + NULL, /* no traversal proc */ + NULL, /* no clear function */ + NULL /* no free function */ +}; + +BEGIN_CONSTANT_TABLE(UPIWINConstants) + /* Message constants */ + CONSTANT_INT_MACRO(WM_NULL) + CONSTANT_INT_MACRO(WM_QUIT) + CONSTANT_INT_MACRO(WM_HWBUTTONDOWN) + CONSTANT_INT_MACRO(WM_HWBUTTONUP) + CONSTANT_INT_MACRO(WM_HWBUTTONCLICK) + CONSTANT_INT_MACRO(WM_TOUCHDOWN) + CONSTANT_INT_MACRO(WM_TOUCHMOVE) + CONSTANT_INT_MACRO(WM_TOUCHUP) + CONSTANT_INT_MACRO(WM_TOUCHCLICK) + /* Raster op constants */ + CONSTANT_INT_MACRO(R2_BLACK) + CONSTANT_INT_MACRO(R2_NOTMERGEPEN) + CONSTANT_INT_MACRO(R2_MASKNOTPEN) + CONSTANT_INT_MACRO(R2_NOTCOPYPEN) + CONSTANT_INT_MACRO(R2_MASKPENNOT) + CONSTANT_INT_MACRO(R2_NOT) + CONSTANT_INT_MACRO(R2_XORPEN) + CONSTANT_INT_MACRO(R2_NOTMASKPEN) + CONSTANT_INT_MACRO(R2_MASKPEN) + CONSTANT_INT_MACRO(R2_NOTXORPEN) + CONSTANT_INT_MACRO(R2_NOP) + CONSTANT_INT_MACRO(R2_MERGENOTPEN) + CONSTANT_INT_MACRO(R2_COPYPEN) + CONSTANT_INT_MACRO(R2_MERGEPENNOT) + CONSTANT_INT_MACRO(R2_MERGEPEN) + CONSTANT_INT_MACRO(R2_WHITE) +END_CONSTANT_TABLE + +PyObject *Epython_init_upiwin_module(void) +{ + PyObject *module; + PUPIWIN_STATE pstate; + + module = PyModule_Create(&DefUPIWIN); + if (!module) + return NULL; + + if (FAILED(Epython_register_constants(module, UPIWINConstants))) + { + Py_DECREF(module); + return NULL; + } + + if (FAILED(Epython_register_bitmap(module))) + { + Py_DECREF(module); + return NULL; + } + + if (FAILED(Epython_register_devctxt(module))) + { + Py_DECREF(module); + return NULL; + } + + /* set up the module state */ + pstate = (PUPIWIN_STATE)PyModule_GetState(module); + pstate->backlight_on = TRUE; + pstate->backlight_level = GSB_BACKLIGHT_DEFAULT; + + return module; +} diff --git a/src/ep_upiwin.h b/src/ep_upiwin.h new file mode 100644 index 0000000..2f5fe99 --- /dev/null +++ b/src/ep_upiwin.h @@ -0,0 +1,47 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __EP_UPIWIN_H_INCLUDED +#define __EP_UPIWIN_H_INCLUDED + +#define PY_SSIZE_T_CLEAN +#include +#include "wintype.h" + +typedef struct tagUPIWIN_STATE { + BOOL backlight_on; + UINT32 backlight_level; +} UPIWIN_STATE, *PUPIWIN_STATE; + +/* method definitions go here */ + +/* ep_backlight.c */ +extern PyObject *Epython_get_backlight(PyObject *self, PyObject *args); +extern PyObject *Epython_set_backlight(PyObject *self, PyObject *args); +extern PyObject *Epython_get_backlight_level(PyObject *self, PyObject *args); +extern PyObject *Epython_set_backlight_level(PyObject *self, PyObject *args); + +/* ep_msg.c */ +extern PyObject *Epython_get_message(PyObject *self, PyObject *args); +extern PyObject *Epython_post_quit_message(PyObject *self, PyObject *args); + +/* ep_graphics.c */ +extern PyObject *Epython_rgb(PyObject *self, PyObject *args); + +#endif /* __EP_UPIWIN_H_INCLUDED */ diff --git a/src/ep_upiwin_tmp.c b/src/ep_upiwin_tmp.c new file mode 100644 index 0000000..97a9f62 --- /dev/null +++ b/src/ep_upiwin_tmp.c @@ -0,0 +1,133 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#define PY_SSIZE_T_CLEAN +#include +#include "scode.h" +#include "fbprimitive.h" +#include "ep_init.h" +#include "ep_util.h" + +static PyObject *do_setpixel(PyObject *self, PyObject *args) +{ + INT32 x, y; + UINT16 color, oldcolor; + BOOL xor; + + if (!PyArg_ParseTuple(args, "iiHi", &x, &y, &color, &xor)) + return NULL; + oldcolor = Fb_setpixel(x, y, color, xor); + return PyLong_FromLong((long)oldcolor); +} + +static PyObject *do_line(PyObject *self, PyObject *args) +{ + INT32 x1, y1, x2, y2; + UINT16 color; + BOOL xor; + + if (!PyArg_ParseTuple(args, "iiiiHi", &x1, &y1, &x2, &y2, &color, &xor)) + return NULL; + Fb_line(x1, y1, x2, y2, color, xor); + Py_RETURN_NONE; +} + +static PyObject *do_rectangle(PyObject *self, PyObject *args) +{ + INT32 x1, y1, x2, y2; + UINT16 color; + BOOL xor; + + if (!PyArg_ParseTuple(args, "iiiiHi", &x1, &y1, &x2, &y2, &color, &xor)) + return NULL; + Fb_rectangle(x1, y1, x2, y2, color, xor); + Py_RETURN_NONE; +} + +static PyObject *do_filled_rectangle(PyObject *self, PyObject *args) +{ + INT32 x1, y1, x2, y2; + UINT16 color; + BOOL xor; + + if (!PyArg_ParseTuple(args, "iiiiHi", &x1, &y1, &x2, &y2, &color, &xor)) + return NULL; + Fb_filled_rectangle(x1, y1, x2, y2, color, xor); + Py_RETURN_NONE; +} + +static PyObject *do_textout(PyObject *self, PyObject *args) +{ + INT32 x, y; + PSTR text; + + if (!PyArg_ParseTuple(args, "iis", &x, &y, &text)) + return NULL; + Fb_textout(x, y, text); + Py_RETURN_NONE; +} + +static PyMethodDef UPIWIN_tmpMethods[] = { + {"setpixel", do_setpixel, METH_VARARGS, "Set a single pixel on the display."}, + {"line", do_line, METH_VARARGS, "Draw a line on the display."}, + {"rectangle", do_rectangle, METH_VARARGS, "Draw a rectangle on the display."}, + {"filled_rectangle", do_filled_rectangle, METH_VARARGS, "Draw a filled rectangle on the display."}, + {"textout", do_textout, METH_VARARGS, "Draw text on the display."}, + {NULL, NULL, 0, NULL} +}; + +static PyModuleDef DefUPIWIN_tmp = { + PyModuleDef_HEAD_INIT, /* standard garbage */ + MOD_NAME_UPIWIN_TMP, /* module name */ + NULL, /* no doc string */ + -1, /* no per-module memory */ + UPIWIN_tmpMethods, /* method defs */ + NULL, /* no slots for multi-phase init */ + NULL, /* no traversal proc */ + NULL, /* no clear function */ + NULL /* no free function */ +}; + +BEGIN_CONSTANT_TABLE(UPIWIN_tmpConstants) + /* primitive color values */ + CONSTANT_INT_MACRO(FBPRIMCLR_BLACK) + CONSTANT_INT_MACRO(FBPRIMCLR_RED) + CONSTANT_INT_MACRO(FBPRIMCLR_GREEN) + CONSTANT_INT_MACRO(FBPRIMCLR_BLUE) + CONSTANT_INT_MACRO(FBPRIMCLR_YELLOW) + CONSTANT_INT_MACRO(FBPRIMCLR_CYAN) + CONSTANT_INT_MACRO(FBPRIMCLR_MAGENTA) + CONSTANT_INT_MACRO(FBPRIMCLR_WHITE) +END_CONSTANT_TABLE + +PyObject *Epython_init_upiwin_tmp_module(void) +{ + PyObject *module; + + module = PyModule_Create(&DefUPIWIN_tmp); + if (module) + { + if (FAILED(Epython_register_constants(module, UPIWIN_tmpConstants))) + { + Py_DECREF(module); + module = NULL; + } + } + return module; +} diff --git a/src/ep_util.c b/src/ep_util.c new file mode 100644 index 0000000..a08d5b1 --- /dev/null +++ b/src/ep_util.c @@ -0,0 +1,94 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#define PY_SSIZE_T_CLEAN +#include +#include "scode.h" +#include "ep_util.h" +#include "log.h" + +void Epython_log_object(int level, const char *label, PyObject *object) +{ + BOOL traced = FALSE; + PyObject *repr; + PCSTR pstr; + + repr = PyObject_Repr(object); + if (repr) + { + ASSERT(PyUnicode_Check(repr)); + pstr = PyUnicode_AsUTF8(repr); + Log(level, "object %s: %s", label, pstr); + traced = TRUE; + Py_DECREF(repr); + } + + if (!traced) + Log(level, "object %s: could not be logged (memory error)", label); +} + +HRESULT Epython_trace_exception(void) +{ + HRESULT hr = E_FAIL; + + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + if (!type) + return S_OK; + + Epython_log_object(LERROR, "exception type", type); + Epython_log_object(LERROR, "exception value", value); + Epython_log_object(LERROR, "exception traceback", value); + + Py_DECREF(type); + Py_DECREF(value); + Py_DECREF(traceback); + return hr; +} + +HRESULT Epython_register_constants(PyObject *module, PCREGCONSTANT const_table) +{ + HRESULT hr = S_OK; + int i = 0, rc; + + while (const_table[i].name) + { + switch (const_table[i].regtype) + { + case 'i': + rc = PyModule_AddIntConstant(module, const_table[i].name, const_table[i].value.ival); + break; + case 's': + rc = PyModule_AddStringConstant(module, const_table[i].name, const_table[i].value.sval); + break; + default: + Log(LERROR, "register_constants type '%c' unknown", const_table[i].regtype); + return E_UNEXPECTED; + } + if (rc) + { + Log(LERROR, "Failed to register constant %s", const_table[i].name); + hr = E_FAIL; + break; + } + ++i; + } + + return hr; +} diff --git a/src/ep_util.h b/src/ep_util.h new file mode 100644 index 0000000..c5d415c --- /dev/null +++ b/src/ep_util.h @@ -0,0 +1,49 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __EP_UTIL_H_INCLUDED +#define __EP_UTIL_H_INCLUDED + +#define PY_SSIZE_T_CLEAN +#include +#include "wintype.h" + +typedef struct tagREGCONSTANT { + CHAR regtype; + PCSTR name; + union { + LONG ival; + PCSTR sval; + } value; +} REGCONSTANT, *PREGCONSTANT; + +typedef const REGCONSTANT *PCREGCONSTANT; + +extern void Epython_log_object(int level, const char *label, PyObject *object); +extern HRESULT Epython_trace_exception(void); +extern HRESULT Epython_register_constants(PyObject *module, PCREGCONSTANT const_table); + +#define BEGIN_CONSTANT_TABLE(name) static const REGCONSTANT name[] = { +#define CONSTANT_INT(name, value) { 'i', name, { .ival = value } }, +#define CONSTANT_INT_MACRO(mac) CONSTANT_INT(#mac, mac) +#define CONSTANT_STRING(name, value) { 's', name, { .sval = value } }, +#define CONSTANT_STRING_MACRO(mac) CONSTANT_STRING(#mac, mac) +#define END_CONSTANT_TABLE { 0, NULL, { .sval = NULL } } }; + +#endif /* __EP_UTIL_H_INCLUDED */ diff --git a/src/fbinit.c b/src/fbinit.c new file mode 100644 index 0000000..84491c1 --- /dev/null +++ b/src/fbinit.c @@ -0,0 +1,133 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "log.h" +#include "fbinit.h" +#include "scode.h" + +/* references to splash screen data in splash.o/splash.bin */ +extern uint8_t _binary_splash_bin_start[]; +extern uint8_t _binary_splash_bin_end; +extern uint8_t _binary_splash_bin_size; + +static int fb_fd = -1; /* framebuffer file descriptor */ + +/* frame buffer information */ +static FBINFO local_info; +PCFBINFO Fb_Info = &local_info; + +UINT16 *Fb_Ptr = NULL; /* pointer to memory-mapped frame buffer */ + +inline static UINT16 makemask(unsigned offset, unsigned length) +{ + return (UINT16)(((1 << length) - 1) << offset); +} + +static void do_cleanup(void) +{ + /* black out the display */ + memset(Fb_Ptr, 0, local_info.screenbytes); + + munmap((void *)Fb_Ptr, local_info.screenbytes); + Fb_Ptr = NULL; + close(fb_fd); + fb_fd = -1; +} + +HRESULT Fb_setup(void) +{ + HRESULT hr = S_OK; + struct fb_fix_screeninfo fixed; + struct fb_var_screeninfo var; + + fb_fd = open(Gconfig.framebuffer_device, O_RDWR); + if (fb_fd == -1) + { + hr = ERRNO_AS_SCODE; + Log(LFATAL, "Unable to open framebuffer device %s (%08X)", Gconfig.framebuffer_device, hr); + return hr; + } + + /* fixed info is needed to get the memory parameters for the display */ + if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fixed)) + { + hr = ERRNO_AS_SCODE; + Log(LFATAL, "Could not get fixed screen info (%08X)", hr); + return hr; + } + + local_info.linebytes = fixed.line_length; + local_info.screenbytes = fixed.smem_len; + + /* variable info is used to get scren geometry and color info */ + if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &var)) + { + hr = ERRNO_AS_SCODE; + Log(LFATAL, "Could not get variable screen info (%08X)", hr); + return hr; + } + + local_info.width = var.xres; + local_info.height = var.yres; + local_info.virtual_width = var.xres_virtual; + local_info.virtual_height = var.yres_virtual; + local_info.bpp = var.bits_per_pixel; + local_info.red_offset = var.red.offset; + local_info.red_length = var.red.length; + local_info.red_mask = makemask(var.red.offset, var.red.length); + local_info.green_offset = var.green.offset; + local_info.green_length = var.green.length; + local_info.green_mask = makemask(var.green.offset, var.green.length); + local_info.blue_offset = var.blue.offset; + local_info.blue_length = var.blue.length; + local_info.blue_mask = makemask(var.blue.offset, var.blue.length); + + Fb_Ptr = (UINT16 *)mmap(0, fixed.smem_len, PROT_READ|PROT_WRITE, MAP_SHARED, fb_fd, 0); + if ((int)Fb_Ptr == -1) + { + hr = ERRNO_AS_SCODE; + Log(LFATAL, "Unable to memmap framebuffer (%08X)", hr); + Fb_Ptr = NULL; + close(fb_fd); + fb_fd = -1; + return hr; + } + + /* display the splash screen */ + memcpy(Fb_Ptr, _binary_splash_bin_start, (size_t)(&_binary_splash_bin_size)); + + hr = Config_exitfunc(do_cleanup); + if (FAILED(hr)) + do_cleanup(); + return hr; +} + +void Fb_clear(void) +{ + memset(Fb_Ptr, 0, local_info.screenbytes); +} diff --git a/src/fbinit.h b/src/fbinit.h new file mode 100644 index 0000000..1575ce0 --- /dev/null +++ b/src/fbinit.h @@ -0,0 +1,52 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __FBINIT_H_INCLUDED +#define __FBINIT_H_INCLUDED + +#include "wintype.h" + +/* info about the frame buffer */ +typedef struct tagFBINFO { + UINT32 width; /* screen width */ + UINT32 height; /* screen height */ + UINT32 virtual_width; /* virtual screen width */ + UINT32 virtual_height; /* virtual screen height */ + UINT32 bpp; /* bits per pixel (16) */ + UINT32 linebytes; /* number of bytes per line */ + UINT32 screenbytes; /* number of bytes for the entire screen */ + UINT16 red_offset; /* offset of "red" bits within pixel word (11) */ + UINT16 red_length; /* number of "red" bits within pixel word (5) */ + UINT16 red_mask; /* mask for the "red" bits in a pixel word */ + UINT16 green_offset; /* offset of "green" bits within pixel word (5) */ + UINT16 green_length; /* number of "green" bits within pixel word (6) */ + UINT16 green_mask; /* mask for the "green" bits in a pixel word */ + UINT16 blue_offset; /* offset of "blue" bits within pixel word (0) */ + UINT16 blue_length; /* number of "blue" bits within pixel word (5) */ + UINT16 blue_mask; /* mask for the "blue" bits in a pixel word */ +} FBINFO; +typedef const FBINFO * const PCFBINFO; + +extern PCFBINFO Fb_Info; /* pointer to screen information */ +extern UINT16 *Fb_Ptr; /* pointer to memory-mapped screen buffer */ + +extern HRESULT Fb_setup(void); +extern void Fb_clear(void); + +#endif /* __FBINIT_H_INCLUDED */ diff --git a/src/fbprimitive.c b/src/fbprimitive.c new file mode 100644 index 0000000..fad520f --- /dev/null +++ b/src/fbprimitive.c @@ -0,0 +1,170 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#include +#include "wintype.h" +#include "log.h" +#include "fbinit.h" +#include "fontengine.h" +#include "fbprimitive.h" + +inline static PUINT16 loc_from_coords(INT32 x, INT32 y) +{ + return Fb_Ptr + (y * Fb_Info->width) + x; +} + +UINT16 Fb_setpixel(INT32 x, INT32 y, UINT16 color, BOOL xor) +{ + UINT16 rc; + PUINT16 loc = loc_from_coords(x, y); + + rc = *loc; + if (xor) + *loc ^= color; + else + *loc = color; + return rc; +} + +void Fb_line(INT32 x1, INT32 y1, INT32 x2, INT32 y2, UINT16 color, BOOL xor) +{ + INT32 tmp; + INT32 dx = x2 - x1; + INT32 dy = y2 - y1; + + /* uses Bresenham's line algorithm with fixed-point arithmetic */ + if (ABS(dx) < ABS(dy)) + { + if (y1 > y2) + { + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + dx = -dx; + dy = -dy; + } + x1 <<= 16; + dx = (dx << 16) / dy; + while (y1 <= y2) + { + Fb_setpixel(x1 >> 16, y1, color, xor); + x1 += dx; + y1++; + } + } + else + { + if (x1 > x2) + { + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + dx = -dx; + dy = -dy; + } + y1 <<= 16; + dy = dx ? (dy << 16) / dx : 0; + while (x1 <= x2) + { + Fb_setpixel(x1, y1 >> 16, color, xor); + y1 += dy; + x1++; + } + } +} + +void Fb_rectangle(INT32 x1, INT32 y1, INT32 x2, INT32 y2, UINT16 color, BOOL xor) +{ + Fb_line(x1, y1, x2, y1, color, xor); + Fb_line(x2, y1 + 1, x2, y2 - 1, color, xor); + Fb_line(x1, y2, x2, y2, color, xor); + Fb_line(x1, y1 + 1, x1, y2 - 1, color, xor); +} + +void Fb_filled_rectangle(INT32 x1, INT32 y1, INT32 x2, INT32 y2, UINT16 color, BOOL xor) +{ + INT32 tmp; + PUINT16 ps, p; + + if (x1 > x2) + { + tmp = x1; + x1 = x2; + x2 = tmp; + } + if (y1 > y2) + { + tmp = y1; + y1 = y2; + y2 = tmp; + } + + ps = loc_from_coords(x1, y1); + for (; y1 <= y2; y1++) + { + p = ps; + for (tmp = x1; tmp <= x2; tmp++) + { + if (xor) + *p++ ^= color; + else + *p++ = color; + } + ps += Fb_Info->width; + } +} + +static void internal_textout(INT32 x, INT32 y, INT32 width, INT32 height, PBYTE gsbits) +{ + INT32 i, j; + BYTE b; + PUINT16 dptr, lbuf; + + if ((width == 0) && (height == 0)) + return; /* must be drawing a space */ + if (((x + width) >= Fb_Info->width) || ((y + height) >= Fb_Info->height)) + return; + dptr = loc_from_coords(x, y); + lbuf = (PUINT16)alloca(width * sizeof(UINT16)); + for (i=0; i> 3) & 0x1F) << 11; + lbuf[j] |= ((UINT16)(b >> 2) & 0x3F) << 5; + lbuf[j] |= ((UINT16)(b >> 3) & 0x1F); + } + + memcpy(dptr, lbuf, width * sizeof(UINT16)); + dptr += Fb_Info->width; + } +} + +void Fb_textout(INT32 x, INT32 y, PCSTR pstr) +{ + FontEng_do_text_out(x, y, pstr, internal_textout); +} diff --git a/src/fbprimitive.h b/src/fbprimitive.h new file mode 100644 index 0000000..3e82ddd --- /dev/null +++ b/src/fbprimitive.h @@ -0,0 +1,41 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __FBPRIMITIVE_H_INCLUDED +#define __FBPRIMITIVE_H_INCLUDED + +#include "wintype.h" + +/* Some predefined "primitive" color values */ +#define FBPRIMCLR_BLACK 0x0000 +#define FBPRIMCLR_RED 0xF800 +#define FBPRIMCLR_GREEN 0x07E0 +#define FBPRIMCLR_BLUE 0x001F +#define FBPRIMCLR_YELLOW 0xFFE0 +#define FBPRIMCLR_CYAN 0x07FF +#define FBPRIMCLR_MAGENTA 0xF81F +#define FBPRIMCLR_WHITE 0xFFFF + +extern UINT16 Fb_setpixel(INT32 x, INT32 y, UINT16 color, BOOL xor); +extern void Fb_line(INT32 x1, INT32 y1, INT32 x2, INT32 y2, UINT16 color, BOOL xor); +extern void Fb_rectangle(INT32 x1, INT32 y1, INT32 x2, INT32 y2, UINT16 color, BOOL xor); +extern void Fb_filled_rectangle(INT32 x1, INT32 y1, INT32 x2, INT32 y2, UINT16 color, BOOL xor); +extern void Fb_textout(INT32 x, INT32 y, PCSTR pstr); + +#endif /* __FBPRIMITIVE_H_INCLUDED */ diff --git a/src/fontengine.c b/src/fontengine.c new file mode 100644 index 0000000..7bc5c5f --- /dev/null +++ b/src/fontengine.c @@ -0,0 +1,107 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#include FT_FREETYPE_H +#include "scode.h" +#include "config.h" +#include "log.h" +#include "fontengine.h" + +static FT_Library library; +static FT_Face stdfont; + +static void fonteng_cleanup(void) +{ + FT_Done_Face(stdfont); + FT_Done_FreeType(library); +} + +HRESULT FontEng_setup(void) +{ + HRESULT hr = S_OK; + FT_Error err; + + err = FT_Init_FreeType(&library); + if (err != 0) + { + Log(LFATAL, "Unable to initialize Freetype (%d)", err); + return E_FAIL; + } + + err = FT_New_Face(library, "/usr/local/share/fonts/truetype/arial.ttf", 0, &stdfont); + if (err != 0) + { + Log(LFATAL, "Unable to load font (%d)", err); + hr = E_FAIL; + goto error_0; + } + + err = FT_Set_Pixel_Sizes(stdfont, 0, 16); + if (err != 0) + { + Log(LFATAL, "Unable to set font size (%d)", err); + hr = E_FAIL; + goto error_1; + } + + hr = Config_exitfunc(fonteng_cleanup); + if (FAILED(hr)) + fonteng_cleanup(); + return hr; + +error_1: + FT_Done_Face(stdfont); +error_0: + FT_Done_FreeType(library); + return hr; +} + +HRESULT FontEng_do_text_out(INT32 x, INT32 y, PCSTR pstr, TEXTOUTFUNC renderfunc) +{ + HRESULT hr = S_OK; + FT_GlyphSlot slot = stdfont->glyph; + FT_UInt glyph_index; + FT_Error err; + + y += (stdfont->size->metrics.ascender >> 6); + + while (*pstr) + { + glyph_index = FT_Get_Char_Index(stdfont, *pstr); + err = FT_Load_Glyph(stdfont, glyph_index, FT_LOAD_DEFAULT); + if (err != 0) + { + hr = E_FAIL; + break; + } + err = FT_Render_Glyph(stdfont->glyph, FT_RENDER_MODE_NORMAL); + if (err != 0) + { + hr = E_FAIL; + break; + } + (*renderfunc)(x + slot->bitmap_left, y - slot->bitmap_top, slot->bitmap.width, + slot->bitmap.rows, slot->bitmap.buffer); + x += slot->advance.x >> 6; + y += slot->advance.y >> 6; + pstr++; + } + return hr; +} diff --git a/src/fontengine.h b/src/fontengine.h new file mode 100644 index 0000000..841fa36 --- /dev/null +++ b/src/fontengine.h @@ -0,0 +1,30 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __FONTENGINE_H_INCLUDED +#define __FONTENGINE_H_INCLUDED + +#include "wintype.h" + +typedef void (*TEXTOUTFUNC)(INT32 x, INT32 y, INT32 width, INT32 height, PBYTE gsbits); + +extern HRESULT FontEng_setup(void); +extern HRESULT FontEng_do_text_out(INT32 x, INT32 y, PCSTR pstr, TEXTOUTFUNC renderfunc); + +#endif /* __FONTENGINE_H_INCLUDED */ diff --git a/src/gfxobj.c b/src/gfxobj.c new file mode 100755 index 0000000..b701bbc --- /dev/null +++ b/src/gfxobj.c @@ -0,0 +1,58 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#include +#include "gfxobj.h" + +void _Go_init(PGFXOBJECT obj, UINT32 sig, UINT32 size) +{ + memset(obj, 0, sizeof(GFXOBJECT)); + obj->sig = sig; + obj->size = size; + obj->refcnt = 1; +} + +void Go_unchain(PGFXOBJECT obj) +{ + if (!(obj->next || obj->prev)) + return; + if (obj->next) + obj->next->prev = obj->prev; + if (obj->prev) + obj->prev->next = obj->next; + obj->prev = obj->next = NULL; +} + +INT32 Go_addref(PGFXOBJECT obj) +{ + return ++(obj->refcnt); +} + +INT32 Go_release(PGFXOBJECT obj) +{ + int rc = --(obj->refcnt); + if (rc == 0) + { + if (obj->dtor) + (*(obj->dtor))(obj); + free(obj); + } + return rc; +} diff --git a/src/gfxobj.h b/src/gfxobj.h new file mode 100755 index 0000000..9b3e3dc --- /dev/null +++ b/src/gfxobj.h @@ -0,0 +1,43 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __GFXOBJ_H_INCLUDED +#define __GFXOBJ_H_INCLUDED + +#include "wintype.h" + +/* type definition for a graphics destructor */ +typedef void (*GFX_DTOR)(PVOID obj); + +/* A graphics object in memory always starts with this. */ +typedef struct tagGFXOBJECT { + UINT32 sig; /* signature so we know what something is */ + UINT32 size; /* size of total allocated memory in block */ + INT32 refcnt; /* reference count */ + GFX_DTOR dtor; /* destructor function called when we're no longer needed */ + struct tagGFXOBJECT *next; /* support double linked lists of obejcts */ + struct tagGFXOBJECT *prev; +} GFXOBJECT, *PGFXOBJECT; + +extern void _Go_init(PGFXOBJECT obj, UINT32 sig, UINT32 size); +extern void Go_unchain(PGFXOBJECT obj); +extern INT32 Go_addref(PGFXOBJECT obj); +extern INT32 Go_release(PGFXOBJECT obj); + +#endif /* __GFXOBJ_H_INCLUDED */ diff --git a/src/gfxtype.h b/src/gfxtype.h new file mode 100755 index 0000000..b969193 --- /dev/null +++ b/src/gfxtype.h @@ -0,0 +1,59 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __GFXTYPE_H_INCLUDED +#define __GFXTYPE_H_INCLUDED + +#include "wintype.h" + +typedef struct tagPOINT { + INT32 x; + INT32 y; +} POINT, *PPOINT; + +typedef struct tagRECT { + INT32 left; + INT32 top; + INT32 right; + INT32 bottom; +} RECT, *PRECT; + +typedef const POINT *PCPOINT; +typedef const RECT *PCRECT; + +typedef UINT32 COLORREF; +typedef PUINT32 PCOLORREF; + +extern BOOL G_set_rect(PRECT rect, int left, int top, int right, int bottom); +extern BOOL G_set_rect_empty(PRECT rect); +extern BOOL G_inflate_rect(PRECT rect, int dx, int dy); +extern BOOL G_offset_rect(PRECT rect, int dx, int dy); +extern BOOL G_is_rect_empty(PCRECT rect); +extern BOOL G_coords_in_rect(PCRECT rect, INT32 x, INT32 y); +extern BOOL G_point_in_rect(PCRECT rect, PCPOINT pt); +extern BOOL G_rect_equal(PCRECT rect1, PCRECT rect2); +extern BOOL G_rect_intersect(PRECT dest, PCRECT src1, PCRECT src2); +extern BOOL G_rect_union(PRECT dest, PCRECT src1, PCRECT src2); + +#define RGB(r, g, b) ((((UINT32)(r)) & 0xFF) | ((((UINT32)(g)) & 0xFF) << 8) | ((((UINT32)(b)) & 0xFF) << 16)) +#define GetRValue(cr) ((UINT32)((cr) & 0xFF)) +#define GetGValue(cr) ((UINT32)(((cr) >> 8) & 0xFF)) +#define GetBValue(cr) ((UINT32)(((cr) >> 16) & 0xFF)) + +#endif /* __GFXTYPE_H_INCLUDED */ diff --git a/src/gpio.c b/src/gpio.c new file mode 100644 index 0000000..5c8aea3 --- /dev/null +++ b/src/gpio.c @@ -0,0 +1,111 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#include +#include "config.h" +#include "log.h" +#include "scode.h" +#include "gpio.h" + +/* GPIO lines used by various peripheral devices */ +#define GLINE_BUTTON1 17 +#define GLINE_BUTTON2 22 +#define GLINE_BUTTON3 23 +#define GLINE_BUTTON4 27 +#define GLINE_BACKLIGHT 18 + +#define PWM_BACKLIGHT 0 /* PWM channel used for backlight */ + +static void do_cleanup(void) +{ + /* close down the backlight lines */ + bcm2835_pwm_set_mode(PWM_BACKLIGHT, 1, 0); + bcm2835_gpio_set_pud(GLINE_BACKLIGHT, BCM2835_GPIO_PUD_OFF); + bcm2835_gpio_fsel(GLINE_BACKLIGHT, BCM2835_GPIO_FSEL_INPT); + + /* close down the button lines */ + bcm2835_gpio_set_pud(GLINE_BUTTON1, BCM2835_GPIO_PUD_OFF); + bcm2835_gpio_fsel(GLINE_BUTTON1, BCM2835_GPIO_FSEL_INPT); + bcm2835_gpio_set_pud(GLINE_BUTTON2, BCM2835_GPIO_PUD_OFF); + bcm2835_gpio_fsel(GLINE_BUTTON2, BCM2835_GPIO_FSEL_INPT); + bcm2835_gpio_set_pud(GLINE_BUTTON3, BCM2835_GPIO_PUD_OFF); + bcm2835_gpio_fsel(GLINE_BUTTON3, BCM2835_GPIO_FSEL_INPT); + bcm2835_gpio_set_pud(GLINE_BUTTON4, BCM2835_GPIO_PUD_OFF); + bcm2835_gpio_fsel(GLINE_BUTTON4, BCM2835_GPIO_FSEL_INPT); + + if (!bcm2835_close()) + Log(LWARN, "Closing BCM2835 library failed"); +} + +HRESULT Gpio_setup(void) +{ + HRESULT hr; + + if (!bcm2835_init()) + { + Log(LFATAL, "Error initializing BCM2835 library"); + return E_FAIL; + } + + /* configure the buttons */ + bcm2835_gpio_set_pud(GLINE_BUTTON1, BCM2835_GPIO_PUD_UP); + bcm2835_gpio_fsel(GLINE_BUTTON1, BCM2835_GPIO_FSEL_INPT); + bcm2835_gpio_set_pud(GLINE_BUTTON2, BCM2835_GPIO_PUD_UP); + bcm2835_gpio_fsel(GLINE_BUTTON2, BCM2835_GPIO_FSEL_INPT); + bcm2835_gpio_set_pud(GLINE_BUTTON3, BCM2835_GPIO_PUD_UP); + bcm2835_gpio_fsel(GLINE_BUTTON3, BCM2835_GPIO_FSEL_INPT); + bcm2835_gpio_set_pud(GLINE_BUTTON4, BCM2835_GPIO_PUD_UP); + bcm2835_gpio_fsel(GLINE_BUTTON4, BCM2835_GPIO_FSEL_INPT); + + /* configure the PWM for the backlight */ + bcm2835_gpio_set_pud(GLINE_BACKLIGHT, BCM2835_GPIO_PUD_OFF); + bcm2835_gpio_fsel(GLINE_BACKLIGHT, BCM2835_GPIO_FSEL_ALT5); + bcm2835_pwm_set_clock(BCM2835_PWM_CLOCK_DIVIDER_2); + bcm2835_pwm_set_mode(PWM_BACKLIGHT, 1, 1); + bcm2835_pwm_set_range(PWM_BACKLIGHT, GSB_BACKLIGHT_MAX + 1); + bcm2835_pwm_set_data(PWM_BACKLIGHT, GSB_BACKLIGHT_DEFAULT); + + hr = Config_exitfunc(do_cleanup); + if (FAILED(hr)) + do_cleanup(); + return hr; +} + +UINT32 Gpio_read_buttons(void) +{ + UINT32 rc = 0; + + if (bcm2835_gpio_lev(GLINE_BUTTON1) == LOW) + rc |= GRB_STATE_BUTTON1; + if (bcm2835_gpio_lev(GLINE_BUTTON2) == LOW) + rc |= GRB_STATE_BUTTON2; + if (bcm2835_gpio_lev(GLINE_BUTTON3) == LOW) + rc |= GRB_STATE_BUTTON3; + if (bcm2835_gpio_lev(GLINE_BUTTON4) == LOW) + rc |= GRB_STATE_BUTTON4; + return rc; +} + +void Gpio_set_backlight(UINT32 level) +{ + if (level > GSB_BACKLIGHT_MAX) + level = GSB_BACKLIGHT_MAX; + bcm2835_pwm_set_data(PWM_BACKLIGHT, level); +} diff --git a/src/gpio.h b/src/gpio.h new file mode 100644 index 0000000..2a5f833 --- /dev/null +++ b/src/gpio.h @@ -0,0 +1,41 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __GPIO_H_INCLUDED +#define __GPIO_H_INCLUDED + +#include "wintype.h" + +#define GPIO_BUTTON_COUNT 4 /* number of GPIO buttons we have */ + +/* state flags for the GPIO buttons */ +#define GRB_STATE_BUTTON1 (1 << 0) +#define GRB_STATE_BUTTON2 (1 << 1) +#define GRB_STATE_BUTTON3 (1 << 2) +#define GRB_STATE_BUTTON4 (1 << 3) + +#define GSB_BACKLIGHT_MAX 1023 /* maximum level for backlight */ + +#define GSB_BACKLIGHT_DEFAULT GSB_BACKLIGHT_MAX + +extern HRESULT Gpio_setup(void); +extern UINT32 Gpio_read_buttons(void); +extern void Gpio_set_backlight(UINT32 level); + +#endif /* __GPIO_H_INCLUDED */ diff --git a/src/log.c b/src/log.c new file mode 100644 index 0000000..88d8ccf --- /dev/null +++ b/src/log.c @@ -0,0 +1,52 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#include +#include +#include +#include "log.h" + +/* string equivalents to the severity values */ +static const char *severities[] = { "FATAL", "ERROR", "WARN ", "INFO ", "DEBUG" }; + +static FILE *logfile = NULL; /* log file pointer */ + +void Log(int level, const char *format, ...) +{ + va_list argp; + struct timeval tv; + struct tm tm; + char timestamp[32]; + char buf[1024]; + + va_start(argp, format); + vsnprintf(buf, 1024, format, argp); + va_end(argp); + + gettimeofday(&tv, NULL); + localtime_r(&(tv.tv_sec), &tm); + strftime(timestamp, 32, "%F %T", &tm); + fprintf(logfile ? logfile : stdout, "%s.%06ld %s %s\n", timestamp, tv.tv_usec, severities[level], buf); +} + +void Log_assert_failed(const char *test, const char *file, int line) +{ + Log(LERROR, "ASSERT FAILED: %s at %s:%d", test, file, line); +} diff --git a/src/log.h b/src/log.h new file mode 100644 index 0000000..c2f82d5 --- /dev/null +++ b/src/log.h @@ -0,0 +1,46 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __LOG_H_INCLUDED +#define __LOG_H_INCLUDED + +/* Logging level severities */ +#define LFATAL 0 /* fatal error */ +#define LERROR 1 /* error */ +#define LWARN 2 /* warning */ +#define LINFO 3 /* information */ +#define LDEBUG 4 /* debugging */ + +extern void Log(int level, const char *format, ...); +extern void Log_assert_failed(const char *test, const char *file, int line); + +/* Current file name definitions for assert macros */ +#define THIS_FILE __FILE__ +#define DECLARE_THIS_FILE() static const char THIS_FILE[] = __FILE__ + +/* Assert macros */ +#ifdef DEBUG_ASSERT +#define ASSERT(x) ((x) ? (void)0 : Log_assert_failed(#x, THIS_FILE, __LINE__)) +#define VERIFY(x) ASSERT(x) +#else +#define ASSERT(x) ((void)0) +#define VERIFY(x) ((void)(x)) +#endif + +#endif /* __LOG_H_INCLUDED */ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..c9c3456 --- /dev/null +++ b/src/main.c @@ -0,0 +1,63 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#include +#include +#include "scode.h" +#include "log.h" +#include "config.h" +#include "gpio.h" +#include "fbinit.h" +#include "fontengine.h" +#include "time_func.h" +#include "ep_init.h" +#include "sysinput.h" + +int main(int argc, char *argv[]) +{ + HRESULT hr; + + /* initialization sequence */ + Time_init(); + hr = Config_setup(argc, argv); + if (FAILED(hr)) + return EXIT_FAILURE; + else if (hr != S_OK) + return EXIT_SUCCESS; + if (FAILED(Fb_setup())) + return EXIT_FAILURE; + if (FAILED(FontEng_setup())) + return EXIT_FAILURE; + if (FAILED(Gpio_setup())) + return EXIT_FAILURE; + if (FAILED(Epython_setup())) + return EXIT_FAILURE; + if (FAILED(Sys_enable_input())) + return EXIT_FAILURE; + Log(LINFO, "Pausing at startup."); + sleep(2); /* wait to show off splash screen */ + + Fb_clear(); + if (FAILED(Epython_run())) + return EXIT_FAILURE; + + Log(LINFO, "Script returned with exit code %d", Sys_Exit_Code); + return Sys_Exit_Code; +} diff --git a/src/msg.h b/src/msg.h new file mode 100644 index 0000000..2733c19 --- /dev/null +++ b/src/msg.h @@ -0,0 +1,46 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __MSG_H_INCLUDED +#define __MSG_H_INCLUDED + +#include "wintype.h" + +#define MSG_ATTRCOUNT 2 + +typedef struct tagMSG { + HANDLE target; + UINT32 message; + UINT_PTR attrs[MSG_ATTRCOUNT]; + TIMESTAMP timestamp; +} MSG, *PMSG; + +#define WM_NULL 0x0000 +#define WM_QUIT 0x0001 + +#define WM_HWBUTTONDOWN 0x0020 +#define WM_HWBUTTONUP 0x0021 +#define WM_HWBUTTONCLICK 0x0022 + +#define WM_TOUCHDOWN 0x0030 +#define WM_TOUCHMOVE 0x0031 +#define WM_TOUCHUP 0x0032 +#define WM_TOUCHCLICK 0x0033 + +#endif /* __MSG_H_INCLUDED */ diff --git a/src/msg_queue.c b/src/msg_queue.c new file mode 100644 index 0000000..62a4124 --- /dev/null +++ b/src/msg_queue.c @@ -0,0 +1,123 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#include +#include +#include "wintype.h" +#include "time_func.h" +#include "msg_queue.h" + +PMSG_QUEUE Mq_alloc(UINT32 nentries) +{ + int sz = sizeof(MSG_QUEUE) + (nentries * sizeof(MSG)); + PMSG_QUEUE rc; + + rc = (PMSG_QUEUE)malloc(sz); + if (!rc) + return NULL; + memset(rc, 0, sz); + rc->startbound = &(rc->messagestore[0]); + rc->endbound = rc->startbound + nentries; + rc->head = rc->tail = rc->startbound; + rc->nentries = nentries; + pthread_mutex_init(&(rc->mutex), NULL); + return rc; +} + +void Mq_destroy(PMSG_QUEUE queue) +{ + pthread_mutex_destroy(&(queue->mutex)); + free(queue); +} + +static void post_internal(PMSG_QUEUE queue, PMSG msg) +{ + PMSG nexttail; + + pthread_mutex_lock(&(queue->mutex)); + nexttail = queue->tail + 1; + if (nexttail == queue->endbound) + nexttail = queue->startbound; + if (nexttail != queue->head) + { + memcpy(queue->tail, msg, sizeof(MSG)); + queue->tail = nexttail; + } + /* else drop the message silently */ + + pthread_mutex_unlock(&(queue->mutex)); +} + +void Mq_post(PMSG_QUEUE queue, HANDLE target, UINT32 message, const UINT_PTR *attrs, int nattrs) +{ + MSG tmpmsg; + + memset(&tmpmsg, 0, sizeof(MSG)); + tmpmsg.target = target; + tmpmsg.message = message; + if (nattrs > MSG_ATTRCOUNT) + nattrs = MSG_ATTRCOUNT; + if (nattrs > 0) + memcpy(&(tmpmsg.attrs), attrs, sizeof(UINT_PTR) * nattrs); + tmpmsg.timestamp = Time_since_start(); + post_internal(queue, &tmpmsg); +} + +void Mq_post2(PMSG_QUEUE queue, HANDLE target, UINT32 message, UINT_PTR attr1, UINT_PTR attr2) +{ + MSG tmpmsg; + + memset(&tmpmsg, 0, sizeof(MSG)); + tmpmsg.target = target; + tmpmsg.message = message; + tmpmsg.attrs[0] = attr1; + tmpmsg.attrs[1] = attr2; + tmpmsg.timestamp = Time_since_start(); + post_internal(queue, &tmpmsg); +} + +BOOL Mq_peek(PMSG_QUEUE queue, PMSG msg, UINT32 flags) +{ + BOOL rc = FALSE; + PMSG nexthead; + + pthread_mutex_lock(&(queue->mutex)); + if (queue->head != queue->tail) + { + nexthead = queue->head + 1; + if (nexthead == queue->endbound) + nexthead = queue->startbound; + memcpy(msg, queue->head, sizeof(MSG)); + if (flags & PEEK_REMOVE) + queue->head = nexthead; + rc = TRUE; + } + pthread_mutex_unlock(&(queue->mutex)); + return rc; +} + +BOOL Mq_is_empty(PMSG_QUEUE queue) +{ + BOOL rc; + pthread_mutex_lock(&(queue->mutex)); + rc = (queue->head == queue->tail); + pthread_mutex_unlock(&(queue->mutex)); + return rc; +} diff --git a/src/msg_queue.h b/src/msg_queue.h new file mode 100644 index 0000000..99ee867 --- /dev/null +++ b/src/msg_queue.h @@ -0,0 +1,53 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __MSG_QUEUE_H_INCLUDED +#define __MSG_QUEUE_H_INCLUDED + +#include +#include "wintype.h" +#include "msg.h" + +/* internal structure of a message queue */ +typedef struct tagMSG_QUEUE { + struct tagMSG_QUEUE *next; /* allow us to be in a singly-linked list */ + PMSG startbound; /* start boundary for message buffer */ + PMSG endbound; /* end boundary for message buffer */ + PMSG head; /* head pointer of message queue */ + PMSG tail; /* tail pointer of message queue */ + UINT32 nentries; /* number of entries possible in message buffer */ + pthread_mutex_t mutex; /* controls access to queue from multiple threads */ + MSG messagestore[0]; /* message buffer */ +} MSG_QUEUE, *PMSG_QUEUE; + +/* flags to Mq_peek */ +#define PEEK_REMOVE 0x0001 /* remove message if found */ +#define PEEK_NOREMOVE 0x0000 /* do not remove message if found */ + +extern PMSG_QUEUE Mq_alloc(UINT32 nentries); +extern void Mq_destroy(PMSG_QUEUE queue); +extern void Mq_post(PMSG_QUEUE queue, HANDLE target, UINT32 message, const UINT_PTR *attrs, int nattrs); +extern void Mq_post2(PMSG_QUEUE queue, HANDLE target, UINT32 message, UINT_PTR attr1, UINT_PTR attr2); +extern BOOL Mq_peek(PMSG_QUEUE queue, PMSG msg, UINT32 flags); +extern BOOL Mq_is_empty(PMSG_QUEUE queue); + +#define Mq_post0(q, tgt, msg) Mq_post2(q, tgt, msg, 0, 0) +#define Mq_post1(q, tgt, msg, attr) Mq_post2(q, tgt, msg, attr, 0) + +#endif /* __MSG_QUEUE_H_INCLUDED */ diff --git a/src/rect.c b/src/rect.c new file mode 100755 index 0000000..0a9608f --- /dev/null +++ b/src/rect.c @@ -0,0 +1,115 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#include "log.h" +#include "gfxtype.h" + +BOOL G_set_rect(PRECT rect, int left, int top, int right, int bottom) +{ + rect->left = left; + rect->top = top; + rect->right = right; + rect->bottom = bottom; + return TRUE; +} + +BOOL G_set_rect_empty(PRECT rect) +{ + memset(rect, 0, sizeof(RECT)); + return TRUE; +} + +BOOL G_inflate_rect(PRECT rect, int dx, int dy) +{ + rect->left += dx; + rect->top += dy; + rect->right -= dx; + rect->bottom -= dy; + return TRUE; +} + +BOOL G_offset_rect(PRECT rect, int dx, int dy) +{ + rect->left += dx; + rect->top += dy; + rect->right += dx; + rect->bottom += dy; + return TRUE; +} + +BOOL G_is_rect_empty(PCRECT rect) +{ + return (rect->right <= rect->left) || (rect->bottom <= rect->top); +} + +BOOL G_coords_in_rect(PCRECT rect, INT32 x, INT32 y) +{ + return (rect->left <= x) && (x < rect->right) && (rect->top <= y) && (y < rect->bottom); +} + +BOOL G_point_in_rect(PCRECT rect, PCPOINT pt) +{ + return G_coords_in_rect(rect, pt->x, pt->y); +} + +BOOL G_rect_equal(PCRECT rect1, PCRECT rect2) +{ + return (memcmp(rect1, rect2, sizeof(RECT)) == 0); +} + +BOOL G_rect_intersect(PRECT dest, PCRECT src1, PCRECT src2) +{ + if (G_is_rect_empty(src1) || G_is_rect_empty(src2)) + { + memset(dest, 0, sizeof(RECT)); + return FALSE; + } + if ((src1->left >= src2->right) || (src2->left >= src1->right) || (src1->top >= src2->bottom) || (src2->top >= src1->bottom)) + { + memset(dest, 0, sizeof(RECT)); + return FALSE; + } + dest->left = MAX(src1->left, src2->left); + dest->top = MAX(src1->top, src2->top); + dest->right = MIN(src1->right, src2->right); + dest->bottom = MIN(src1->bottom, src2->bottom); + ASSERT(dest->left <= dest->right); + ASSERT(dest->top <= dest->bottom); + return TRUE; +} + +BOOL G_rect_union(PRECT dest, PCRECT src1, PCRECT src2) +{ + if (G_is_rect_empty(src1)) + { + memcpy(dest, src2, sizeof(RECT)); + return !G_is_rect_empty(src2); + } + else if (G_is_rect_empty(src2)) + { + memcpy(dest, src1, sizeof(RECT)); + return TRUE; + } + dest->left = MIN(src1->left, src2->left); + dest->top = MIN(src1->top, src2->top); + dest->right = MAX(src1->right, src2->right); + dest->bottom = MAX(src1->bottom, src2->bottom); + return TRUE; +} diff --git a/src/scode.h b/src/scode.h new file mode 100644 index 0000000..acd472b --- /dev/null +++ b/src/scode.h @@ -0,0 +1,89 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __SCODE_H_INCLUDED +#define __SCODE_H_INCLUDED + +#include "wintype.h" + +/*------------------------------------------------------------------- + * Status codes are defined as follows: + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |S| Facility | Code | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 9 8 7 6 5 4 3 2 1 0 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * + * S = Severity: 0 = success, 1 = error + * Facility = Facility code + * Code = Specific error code + *------------------------------------------------------------------- + */ + +/* Severity codes */ +#define SEVERITY_SUCCESS 0x00000000 +#define SEVERITY_ERROR 0x80000000 + +/* Facility codes - compatible with M$ */ +#define FACILITY_NULL 0 +#define FACILITY_RPC 1 +#define FACILITY_STORAGE 3 +#define FACILITY_ITF 4 +#define FACILITY_UNIX 5 +#define FACILITY_UPIWIN 6 + +#define SUCCEEDED(s) (((s) & SEVERITY_ERROR) == 0) +#define FAILED(s) (((s) & SEVERITY_ERROR) != 0) + +#define SCODE_FACILITY(s) (((s) >> 16) & 0x7FFF) +#define SCODE_CODE(s) ((s) & 0xFFFF) + +#define MAKE_SCODE(sev, fac, err) ((SCODE)((sev) | (((fac) & 0x7FFF) << 16) | ((err) & 0xFFFF))) + +#define SCODE_FROM_ERRNO(x) MAKE_SCODE(SEVERITY_ERROR, FACILITY_UNIX, (x)) +#define ERRNO_AS_SCODE SCODE_FROM_ERRNO(errno) + +#define SCODE_CAST(x) ((SCODE)(x)) + +/* Basic success codes */ +#define S_OK SCODE_CAST(0x00000000) /* OK return */ +#define S_FALSE SCODE_CAST(0x00000001) /* "False" return */ + +/* Basic error codes */ +#define E_NOTIMPL SCODE_CAST(0x80000001) /* not implemented */ +#define E_OUTOFMEMORY SCODE_CAST(0x80000002) /* out of memory */ +#define E_INVALIDARG SCODE_CAST(0x80000003) /* invalid argument */ +#define E_NOINTERFACE SCODE_CAST(0x80000004) /* no such interface */ +#define E_POINTER SCODE_CAST(0x80000005) /* invalid pointer */ +#define E_HANDLE SCODE_CAST(0x80000006) /* invalid handle */ +#define E_ABORT SCODE_CAST(0x80000007) /* aborted operation */ +#define E_FAIL SCODE_CAST(0x80000008) /* unspecified failure */ +#define E_ACCESSDENIED SCODE_CAST(0x80000009) /* access denied */ +#define E_PENDING SCODE_CAST(0x8000000A) /* data not yet available */ +#define E_BOUNDS SCODE_CAST(0x8000000B) /* access outside valid range */ +#define E_CHANGED_STATE SCODE_CAST(0x8000000C) /* object changed state, result now invalid */ +#define E_ILLEGAL_STATE_CHANGE SCODE_CAST(0x8000000D) /* illegal state change */ +#define E_ILLEGAL_METHOD_CALL SCODE_CAST(0x8000000E) /* illegal method call */ +#define E_UNEXPECTED SCODE_CAST(0x8000FFFF) /* unexpected error */ + +/* UPIWIN-specific errorcodes */ +#define UPIWIN_E_INVALIDSCRIPT SCODE_CAST(0x80060000) /* invalid script file */ +#define UPIWIN_E_NOSCRIPT SCODE_CAST(0x80060001) /* no script specified */ + +#endif /* __SCODE_H_INCLUDED */ diff --git a/src/stockobj.c b/src/stockobj.c new file mode 100755 index 0000000..cb12205 --- /dev/null +++ b/src/stockobj.c @@ -0,0 +1,75 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#include +#include "wintype.h" +#include "bitmap.h" + +/* references to the icon data */ +extern uint8_t _binary_i_freehand_bin_start[]; +extern uint8_t _binary_i_freehand_bin_end; +extern uint8_t _binary_i_freehand_bin_size; + +extern uint8_t _binary_i_line_bin_start[]; +extern uint8_t _binary_i_line_bin_end; +extern uint8_t _binary_i_line_bin_size; + +extern uint8_t _binary_i_rect_bin_start[]; +extern uint8_t _binary_i_rect_bin_end; +extern uint8_t _binary_i_rect_bin_size; + +extern uint8_t _binary_i_fillrect_bin_start[]; +extern uint8_t _binary_i_fillrect_bin_end; +extern uint8_t _binary_i_fillrect_bin_size; + +extern uint8_t _binary_i_undo_bin_start[]; +extern uint8_t _binary_i_undo_bin_end; +extern uint8_t _binary_i_undo_bin_size; + +extern uint8_t _binary_i_clear_bin_start[]; +extern uint8_t _binary_i_clear_bin_end; +extern uint8_t _binary_i_clear_bin_size; + +typedef struct tagSTOCKBITMAPDESC { + PCSTR name; + INT32 width; + INT32 height; + const void *data; +} STOCKBITMAPDESC; + +static const STOCKBITMAPDESC stock_bitmaps[] = { + {"freehand", 48, 48, _binary_i_freehand_bin_start }, + {"line", 48, 48, _binary_i_line_bin_start }, + {"rect", 48, 48, _binary_i_rect_bin_start }, + {"fillrect", 48, 48, _binary_i_fillrect_bin_start }, + {"undo", 48, 48, _binary_i_undo_bin_start }, + {"clear", 48, 48, _binary_i_clear_bin_start }, + {NULL, 0, 0, NULL } +}; + +PBITMAP _BMP_GetStock(PCSTR name) +{ + INT32 i; + + for (i = 0; stock_bitmaps[i].name; ++i) + if (strcmp(name, stock_bitmaps[i].name) == 0) + return BMP_Create(stock_bitmaps[i].width, stock_bitmaps[i].height, stock_bitmaps[i].data); + return NULL; +} diff --git a/src/sysinput.c b/src/sysinput.c new file mode 100644 index 0000000..0682c49 --- /dev/null +++ b/src/sysinput.c @@ -0,0 +1,255 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "scode.h" +#include "config.h" +#include "log.h" +#include "msg_queue.h" +#include "gpio.h" +#include "fbinit.h" +#include "time_func.h" + +#define INPUT_EVENT_BATCH 16 /* number of events to retrieve from touchscreen at once */ + +PMSG_QUEUE Sys_Queue = NULL; /* system message queue */ +INT32 Sys_Exit_Code = -1; /* system exit code, set on WM_QUIT */ +static int ts_fd = 0; /* file descriptor for touchscreen */ + +static pthread_t ithread; /* input thread handle */ +static volatile sig_atomic_t running = 1; /* "running" flag for input thread */ + +static pthread_mutex_t wait_mutex = PTHREAD_MUTEX_INITIALIZER; /* mutex for waiting on input */ +static pthread_cond_t wait_cond = PTHREAD_COND_INITIALIZER; /* condition for waiting on input */ + +/* Local data for poll_buttons() */ +static UINT32 last_bstate = 0; /* previous button state */ +static TIMESTAMP button_event_ok[GPIO_BUTTON_COUNT]; /* timestamps to debounce events */ +static TIMESTAMP button_down_time[GPIO_BUTTON_COUNT]; /* timestamps for click detection */ + +/* Local data for poll_touchscreen() */ +static UINT_PTR touch_x = 0; /* X coordinate to send with next message */ +static UINT_PTR touch_y = 0; /* Y coordinate to send with next message */ +static UINT32 touch_nextmsg = WM_TOUCHMOVE; /* identifier of next message to send */ +static UINT_PTR touch_down_x, touch_down_y; /* location of the touch-down event for click detection */ +static TIMESTAMP touch_down_time; /* timestamp for click detection */ + +static BOOL poll_buttons(void) +{ + BOOL posted = FALSE; + UINT32 st, down, up, mask; + UINT_PTR attr; + TIMESTAMP now; + + /* poll hardware buttons */ + st = Gpio_read_buttons(); + if (st != last_bstate) + { + now = Time_since_start(); + up = last_bstate & ~st; + down = st & ~last_bstate; + for (attr = 1, mask = GRB_STATE_BUTTON1; attr <= GPIO_BUTTON_COUNT; attr++, mask <<= 1) + { + if (now < button_event_ok[attr - 1]) + continue; /* this is a "contact bounce" event, don't bother */ + if (up & mask) + { + /* reset contact bounce timer - only seems to happen after button releases */ + button_event_ok[attr - 1] = now + Gconfig.button_debounce; + Mq_post1(Sys_Queue, 0, WM_HWBUTTONUP, attr); + if ((now - button_down_time[attr - 1]) <= Gconfig.click_time) + Mq_post1(Sys_Queue, 0, WM_HWBUTTONCLICK, attr); + posted = TRUE; + } + else if (down & mask) + { + Mq_post1(Sys_Queue, 0, WM_HWBUTTONDOWN, attr); + button_down_time[attr - 1] = now; + posted = TRUE; + } + } + last_bstate = st; + } + return posted; +} + +static BOOL poll_touchscreen(void) +{ + BOOL posted = FALSE; + int nb, nev, xerrno, i; + TIMESTAMP now; + struct input_event buffer[INPUT_EVENT_BATCH]; + + nb = read(ts_fd, buffer, INPUT_EVENT_BATCH * sizeof(struct input_event)); + if (nb == -1) + { + xerrno = errno; + if ((xerrno != EAGAIN) && (xerrno != EWOULDBLOCK)) + Log(LERROR, "Error reading from touchscreen device (%d)", xerrno); + return FALSE; + } + else if (nb == 0) + { + Log(LERROR, "Unexpected end of file reading from touchscreen device"); + return FALSE; + } + + nev = nb / sizeof(struct input_event); + xerrno = nev * sizeof(struct input_event); + if (nb > xerrno) + Log(LERROR, "read %d bytes from touchscreen but we can only use %d", nb, xerrno); + + for (i=0; iheight - buffer[i].value; + else if (buffer[i].code == ABS_Y) + touch_x = buffer[i].value; + break; + + case EV_KEY: + if (buffer[i].code == BTN_TOUCH) + touch_nextmsg = (buffer[i].value ? WM_TOUCHDOWN : WM_TOUCHUP); + break; + + default: + break; + } + } + return posted; +} + +static void *input_thread(void *arg) +{ + BOOL gotinput; + + /* clear all state at startup */ + last_bstate = 0; + memset(button_event_ok, 0, GPIO_BUTTON_COUNT * sizeof(TIMESTAMP)); + touch_x = touch_y = 0; + touch_nextmsg = WM_TOUCHMOVE; + + while (running) + { + gotinput = poll_buttons(); + gotinput = poll_touchscreen() || gotinput; + if (gotinput) + { + pthread_mutex_lock(&wait_mutex); + pthread_cond_signal(&wait_cond); + pthread_mutex_unlock(&wait_mutex); + } + } + return NULL; +} + +static void do_disable_input(void) +{ + running = 0; + pthread_join(ithread, NULL); + close(ts_fd); + ts_fd = -1; + Mq_destroy(Sys_Queue); + Sys_Queue = NULL; +} + +HRESULT Sys_enable_input(void) +{ + HRESULT rc = S_OK; + int threadrc; + + Sys_Queue = Mq_alloc(Gconfig.sys_mq_length); + if (!Sys_Queue) + { + Log(LFATAL, "Unable to allocate system message queue."); + return E_OUTOFMEMORY; + } + + ts_fd = open(Gconfig.touchscreen_device, O_RDONLY|O_NONBLOCK); + if (ts_fd < 0) + { + rc = ERRNO_AS_SCODE; + Log(LFATAL, "Unable to open touchscreen device %s (%08X).", Gconfig.touchscreen_device, rc); + goto error_0; + } + + running = 1; + threadrc = pthread_create(&ithread, NULL, input_thread, NULL); + if (threadrc != 0) + { + rc = SCODE_FROM_ERRNO(threadrc); + Log(LFATAL, "Unable to start system input thread (%08X).", rc); + goto error_1; + } + + rc = Config_exitfunc(do_disable_input); + if (FAILED(rc)) + do_disable_input(); + return rc; + +error_1: + close(ts_fd); + ts_fd = -1; +error_0: + Mq_destroy(Sys_Queue); + return rc; +} + +void Sys_wait_for_input(void) +{ + pthread_mutex_lock(&wait_mutex); + while (Mq_is_empty(Sys_Queue)) + pthread_cond_wait(&wait_cond, &wait_mutex); + pthread_mutex_unlock(&wait_mutex); +} diff --git a/src/sysinput.h b/src/sysinput.h new file mode 100644 index 0000000..d3ecb20 --- /dev/null +++ b/src/sysinput.h @@ -0,0 +1,32 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __SYSINPUT_H_INCLUDED +#define __SYSINPUT_H_INCLUDED + +#include "wintype.h" +#include "msg_queue.h" + +extern PMSG_QUEUE Sys_Queue; +extern INT32 Sys_Exit_Code; + +extern HRESULT Sys_enable_input(void); +extern void Sys_wait_for_input(void); + +#endif /* __SYSINPUT_H_INCLUDED */ diff --git a/src/time_func.c b/src/time_func.c new file mode 100644 index 0000000..4c0907e --- /dev/null +++ b/src/time_func.c @@ -0,0 +1,44 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#include +#include +#include "time_func.h" + +static TIMESTAMP start_timestamp = 0; /* time since epoch at start of run */ + +TIMESTAMP Time_since_epoch(void) +{ + TIMESTAMP rc; + struct timeval tv; + + gettimeofday(&tv, NULL); + rc = (tv.tv_sec * (TIMESTAMP)1000) + (tv.tv_usec / (TIMESTAMP)1000); + return rc; +} + +TIMESTAMP Time_since_start(void) +{ + return Time_since_epoch() - start_timestamp; +} + +void Time_init(void) +{ + start_timestamp = Time_since_epoch(); +} diff --git a/src/time_func.h b/src/time_func.h new file mode 100644 index 0000000..2648d85 --- /dev/null +++ b/src/time_func.h @@ -0,0 +1,29 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __TIMEFUNC_H_INCLUDED +#define __TIMEFUNC_H_INCLUDED + +#include "wintype.h" + +extern TIMESTAMP Time_since_epoch(void); +extern TIMESTAMP Time_since_start(void); +extern void Time_init(void); + +#endif /* __TIMEFUNC_H_INCLUDED */ diff --git a/src/wintype.h b/src/wintype.h new file mode 100644 index 0000000..9e1d6dc --- /dev/null +++ b/src/wintype.h @@ -0,0 +1,175 @@ +/* + * UPIWIN - Micro Pi Windowing Framework Kernel + * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *------------------------------------------------------------------------- + */ +#ifndef __WINTYPE_H_INCLUDED +#define __WINTYPE_H_INCLUDED + +#include + +/* Integral limit values */ +/*#define INT16_MIN 0x8000 - defined in stdint.h */ +/*#define INT16_MAX 0x7FFF - defined in stdint.h */ +#define UINT16_MIN 0 +/*#define UINT16_MAX 0xFFFF - defined in stdint.h*/ +/*#define INT32_MIN 0x80000000 - defined in stdint.h*/ +/*#define INT32_MAX 0x7FFFFFFF - defined in stdint.h*/ +#define UINT32_MIN 0 +/*#define UINT32_MAX 0xFFFFFFFF - defined in stdint.h*/ +/*#define INT64_MIN 0x8000000000000000 - defined in stdint.h*/ +/*#define INT64_MAX 0x7FFFFFFFFFFFFFFF - defined in stdint.h*/ +#define UINT64_MIN 0 +/*#define UINT64_MAX 0xFFFFFFFFFFFFFFFF - defined in stdint.h*/ + +#define INT_PTR_MIN INTPTR_MIN +#define INT_PTR_MAX INTPTR_MAX +#define UINT_PTR_MIN 0 +#define UINT_PTR_MAX UINTPTR_MAX +#define DWORD_MIN UINT32_MIN +#define DWORD_MAX UINT32_MAX + +/* Number of bits */ +#define INT16_BITS 16 +#define UINT16_BITS 16 +#define INT32_BITS 32 +#define UINT32_BITS 32 +#define INT64_BITS 64 +#define UINT64_BITS 64 + +#define LOG_PTRSIZE 2 /* log2(sizeof(void *)) */ + +#define LOG_INTSIZE 2 /* log2(sizeof(int)) */ +#define LOG_UINTSIZE 2 /* log2(sizeof(UINT32)) */ +#define LOG_INT64SIZE 3 /* log2(sizeof(long long)) */ + +#define PTRSIZE (1U << LOG_PTRSIZE) +#define PTR_MASK (PTRSIZE - 1) +#define PTR_CEILING(a) (((a) + PTR_MASK) & ~PTR_MASK) + +/* Boolean values */ +#define TRUE 1 +#define FALSE 0 + +/* NULL value */ +#ifndef NULL +#define NULL 0 +#endif + +/* Integral types */ +typedef int16_t INT16; +typedef uint16_t UINT16; +typedef int32_t INT32; +typedef uint32_t UINT32; +typedef int64_t INT64; +typedef uint64_t UINT64; + +typedef UINT16 WORD; +typedef UINT32 DWORD; +typedef UINT64 QWORD; +typedef INT32 LONG; +typedef UINT32 ULONG; +typedef INT64 LONG64; +typedef UINT64 ULONG64; + +typedef INT32 INT; +typedef UINT32 UINT; + +typedef INT64 LONGLONG; +typedef UINT64 ULONGLONG; + +typedef intptr_t INT_PTR; +typedef uintptr_t UINT_PTR; + +typedef UINT_PTR SIZE_T; +typedef INT_PTR SSIZE_T; + +/* Base pointer types */ +typedef INT16 *PINT16; +typedef UINT16 *PUINT16; +typedef INT32 *PINT32; +typedef UINT32 *PUINT32; +typedef INT64 *PINT64; +typedef UINT64 *PUINT64; +typedef SIZE_T *PSIZE_T; +typedef void *PVOID; +typedef const void *PCVOID; +typedef WORD *PWORD; +typedef DWORD *PDWORD; +typedef QWORD *PQWORD; +typedef LONGLONG *PLONGLONG; +typedef ULONGLONG *PULONGLONG; + +/* Pointer-to-pointer types */ +typedef PVOID *PPVOID; + +/* Character types */ +typedef char CHAR; +typedef unsigned char UCHAR; +typedef unsigned char BYTE; +typedef uint16_t WCHAR; + +typedef CHAR *PCHAR; +typedef const CHAR *PCCHAR; +typedef UCHAR *PUCHAR; +typedef BYTE *PBYTE; +typedef const BYTE *PCBYTE; +typedef WCHAR *PWCHAR; +typedef const WCHAR *PCWCHAR; +typedef PCCHAR *PPCCHAR; +typedef CHAR *PSTR; +typedef const CHAR *PCSTR; +typedef WCHAR *PWSTR; +typedef const WCHAR *PCWSTR; + +typedef PCSTR *PPCSTR; + +/* Boolean type */ +typedef int BOOL; + +/* Handle type */ +typedef UINT_PTR HANDLE; +typedef HANDLE *PHANDLE; + +/* Status code/result types */ +typedef UINT32 SCODE; +typedef SCODE *PSCODE; +typedef SCODE HRESULT; + +typedef UINT64 TIMESTAMP; + +#define MAKEBOOL(val) ((val) ? TRUE : FALSE) +#define OFFSETOF(struc, field) ((UINT_PTR)(&(((struc *)0)->field))) +#ifndef MIN +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#endif +#ifndef MAX +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) +#endif +#define ABS(v) ((v) < 0 ? -(v) : (v)) + +#define MAKEWORD(a, b) ((WORD)((((UINT_PTR)(a)) & 0xFF) | ((((UINT_PTR)(b)) & 0xFF) << 8))) +#define MAKELONG(a, b) ((LONG)((((UINT_PTR)(a)) & 0xFFFF) | ((((UINT_PTR)(b)) & 0xFFFF) << 16))) +#define MAKELONG64(a, b) ((LONG64)((((UINT64)(a)) & 0xFFFFFFFF) | ((((UINT64)(b)) & 0xFFFFFFFF) << 32))) +#define LODWORD(l) ((DWORD)(((UINT64)(l)) & 0xFFFFFFFF)) +#define HIDWORD(l) ((DWORD)((((UINT64)(l)) >> 32) & 0xFFFFFFFF)) +#define LOWORD(l) ((WORD)(((UINT_PTR)(l)) & 0xFFFF)) +#define HIWORD(l) ((WORD)((((UINT_PTR)(l)) >> 16) & 0xFFFF)) +#define LOBYTE(w) ((BYTE)(((UINT_PTR)(w)) & 0xFF)) +#define HIBYTE(w) ((BYTE)((((UINT_PTR)(w)) >> 8) & 0xFF)) + +#endif /* __WINTYPE_H_INCLUDED */