├── POLICY.md ├── README.md ├── assignments ├── book.md ├── ezdib │ ├── LICENSE │ ├── Makefile │ ├── README │ ├── ezdib.c │ ├── ezdib.h │ ├── ezdib.sln │ ├── ezdib.vcproj │ └── main.c ├── gram.txt ├── homework1.pdf ├── homework2.pdf ├── homework3.pdf ├── homework4.pdf ├── nqueen-sat.c ├── peer+evaluation.xlsx ├── reading+group.md └── report.docx ├── notes ├── .gitkeep ├── algorithm.pdf ├── cardinality.pdf ├── counting.pdf ├── course+overview.pdf ├── graph.pdf ├── halting+problem.pdf ├── induction.pdf ├── inference.pdf ├── predicate+logic.pdf ├── probability.pdf ├── proof.pdf ├── prop+logic+solver.pdf ├── propositional+logic.pdf ├── recursion.pdf ├── relation.pdf ├── sequence.pdf ├── set+function.pdf ├── test1.pdf ├── test2.pdf ├── test3.pdf └── test4.pdf └── resource ├── 17-final.pdf ├── 17-midterm.pdf ├── 18-final.pdf ├── 18-midterm.pdf ├── 18-quiz-01.pdf ├── 18-quiz-02.pdf ├── 19-final.pdf ├── 19-midterm-01.pdf ├── 19-midterm-02.pdf ├── 20-final.pdf └── 20-midterm.pdf /POLICY.md: -------------------------------------------------------------------------------- 1 | Class Policy 2 | ===== 3 | ### Communication ### 4 | #### English #### 5 | English is the official language of this course. As specified in the university 6 | policy, students in a 100% English course must use English in all formal 7 | activities, for instance writing homework, assignment report, midterm and final 8 | exam answers; non-English parts will not be counted at all kinds of evaluations. 9 | 10 | The instructor must use English in delivering class contents (e.g., lecture, 11 | assignments, exams). Students are highly recommended to use English for asking 12 | questions and participating in discussion. 13 | 14 | Yet, to promote active participation, students are allowed to use Korean for 15 | question and class participatio; in this case, the instructor will repeat 16 | Korean sayings in English. In addition, the instructor can use Korean to 17 | rephrase what he had already said in English; in this case as well, 18 | the instructor repeat in English what he said in Korean for double-check. 19 | 20 | c.f. [Is Handong 21 | Global?](http://www.hgupress.com/news/articleView.html?idxno=6078) 22 | by Prof. Scott Lincoln 23 | 24 | #### Contact with Instructor #### 25 | **Questions**: Use the class channel in Slack. 26 | Make questions publicly, so that I can share the question and my answer 27 | easily with all class members. For this reason, the TAs and I will not 28 | response to any personal contacts (e.g., Slack DM, e-mail). 29 | 30 | **Administrative requests**: Use Handong LMS and LMS Messaging. 31 | For claiming attendance update and discussion point, you must put a post to 32 | ``Open Board``, or leave a comment at the corresponding post publicly. 33 | This makes the claiming process accountable and transparent to all class members. 34 | 35 | For a case where privacy matters, you first write a public post and then 36 | send the instructor a message via LMS to tranfer privacy-sensitive information 37 | (e.g., a proof for an approved absence). 38 | 39 | **Counseling session**: Students can request a counselling session to the 40 | instructor to ask academic advice. 41 | To make an appointment with the instructor, submit an answer to the following 42 | pre-interview form: https://forms.gle/KbREJ1b5S13nD51V7. 43 | When a new submission is received, the instructor will send a reply to arrange 44 | a personal counseling session. Note that the instructor does not arrange any 45 | personal meeting at an exam season. 46 | 47 | **Improper solicitation**: All kinds of improper solicitations are strictly 48 | forbidden as declared in the Improper Solicitation and Graft Act 49 | (aka. *Kim Young-ran* Act). For example: 50 | 51 | 1. Students MUST NOT give a gift in any form to the instructor or TA (even a can of coffee) 52 | while they are officially students in Handong University 53 | 1. Students MUST NOT ask the instructor or TA to change their gradings or evaluation results. Meanwhile, students can claim for correcting errors in evaluation. 54 | 1. Students MUST NOT ask the instructor or TA any kind of unfair evaluations, even for exceptional cases. If you want to claim for an execute due to your exceptional circumstance, you must discuss the concern with the Student's Academic Affair Team. Only upon the official request from the Student's Academic Affair Team, the instructor may change the rule/policy for execuse. 55 | Any violation of these will be reported to the Academic Affair Team for treatments. 56 | 57 | c.f. (1) [학교에서 알아야 할 김영란법 58 | Q&A](http://tong.joins.com/archives/32930) 59 | (2) [학생들도 "청탁 마세요"](http://www.kunews.ac.kr/news/articleView.html?idxno=23393) 60 | 61 | #### Teaching assistant (TA) #### 62 | TAs of the course works primary for assisting the instructor in conducting 63 | meetings, in supporting students for accomplishing assignments, and in 64 | processing educational materials such as grading exam/quizzes/assignments. 65 | There may be help desk sessions offered by TAs if required. 66 | 67 | ### Class Materials ### 68 | * You are MUST NOT record the audio or video of the class meeting (even for your personal use). 69 | * Illegal uses of the class materials are strictly prohibited. Check and uphold their copyrights. 70 | 71 | ### Class Attendance ### 72 | * The instructor will check the attendance of each student at every class. 73 | Each student must declare his/her attendance at a class by responsing to the 74 | instructor. 75 | * If you failed to delcare your attendance due to technical problem, 76 | put a claiming post to ``Open Board`` in Handong LMS. 77 | * Approved absence (공인출석) is accepted only if (1) the instructor confirms that your case adheres to Act 8-34 of the HGU rule, and at the same time (3) you submit the proof 78 | * Act 8-34 of the HGU rule: http://rule.handong.edu/Gku.asp?Pun=3&Jang=3&Gku=1&Flag=SEARCH&Jo=34&Search_Word=#34 79 | >아래에 명시된 사유로 인한 수업 불참은 공인출석으로 처리되어 결석으로 간주되지 않으나 사고발생전이나 발생즉시 또는 부득이한 경우에는 발생일로부터 15일 이내에 증빙서류을 첨부하여 담임지도교수와 학과(부)장을 경유, 담당교수에게 직접 제출하여야 하고 제5호에서 제9호까지는 교무처장의 사전승인 받은 후 담당교수에게 직접 제출하여야 한다. 다만, 계절학기의 경우 공인출석사유별 최대 허용일을 교무처장이 별도로 정한다.(개정 2017.12.15) 80 | 1. 직계가족의 사망 및 이와 동등한 사고 [5일] 81 | 2. 학생의 입원기간 및 통원치료로 출석이 어려운 경우(개정2016.11.21) [2주] 82 | 3. 징병검사 등 병역의무로 인한 사유 [실제소요 기간] 83 | 4. 군제대 복학 시 개강후 4주이내 복학자 [해당기간] 84 | 5. 졸업여행, 교육실습, 야외실습 및 각 학과(부) 학술여행 [해당기간] 85 | 6. 정부기관의 요청에 의한 동원 및 특별회합 [해당기간] 86 | 7. 국제회합 및 이에 준하는 학생 활동 [실제 소요기간] 87 | 8. 졸업예정자로서 국가 또는 기업체의 채용시험에 응시하는 사유 [실제 소요기간] 88 | 9. 졸업예정자(8학기 이상 등록자)의 조기취업 등으로 인한 사유 [해당기간] 89 | 10. 기타 총장이 허가하는 경우 [해당기간] 90 | 91 | * Proof submission: aftering writting a post that you are claiming an approved 92 | absence, send the instructor an image file of your proof via LMS messaging. 93 | * A student CANNOT pass this course (i.e., get 'F') if he/she misses more than 7 classes (>25%). 94 | Note that it is impossible to make any excuse for this policy, since it is 95 | regulated by the MOE of the Korea government. 96 | 97 | ### Failures ### 98 | A student will be rejected (i.e., get F) without any excuse for the following cases: 99 | * Acts or attempts of conducting academic dishonesty, including the following cases: 100 | * To see other's answer or unauthorized materials (including online ones) at an exam, quiz, assignment, etc. 101 | * To show his/her answer at an exam, quiz, assignment, etc. 102 | * To fake a point that matters to grading (attendance, discussion, peer evaluation) 103 | 104 | * Or, missing more than 7 meetings (see the Meeting Attendance part) 105 | 106 | * Or, not taking midterm or final exam 107 | 108 | c.f. [Handong CSEE Code of Academic Ethics](http://csee.handong.edu/wp-content/uploads/2018/02/HGU-CSEE-Standard_English_v0.2.pdf) 109 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Discrete Mathematics, Fall 2021 # 2 | 3 | ### Course information ### 4 | * Meeting time: Tue/Fri, 4:00--5:15 PM 5 | * Meeting location 6 | * onsite: OH 401 7 | * online:[https://handong.zoom.us/my/hongshin](https://handong.zoom.us/my/hongshin) 8 | * Instructor: Shin Hong https://hongshin.github.io / hongshin@handong.edu 9 | 10 | ### Course objectives ### 11 | This course aims to equip beginner-level students majored in Computer Science 12 | with essential mathematics for pursing their study in Computer Science. 13 | It is designed to articulate students in reading and writing formal description 14 | of mathematical concept, understanding basics of computation, and reasoning 15 | properties of data structures (e.g. sets, relations, permutations, graphs, and 16 | trees). This course is also purposed to broaden student's interests in 17 | Computer Science by engaging the fundamental concepts with their applications in 18 | real-world. 19 | 20 | ### Class policies ### 21 | [POLICY.md](POLICY.md) 22 | 23 | ### Materials ### 24 | #### Textbook #### 25 | [Discrete Mathematics and Its Applications, 8/e](http://www.firstbook.kr/bbs/board.php?bo_table=books&wr_id=289) authored by Kenneth. H. Rosen 26 | This book can be found in *Handong Book* on campus. It is **mandatory** for each student to hold a copy of this textbook: it will be assumed that everyone is able to access the textbook by himself/herself anytime in this semester for doing homework, assignmenets, etc. 27 | 28 | #### Lecture Notes #### 29 | * [#Test 4](notes/test4.pdf) (17 Dec) 30 | * [Graph](notes/graph.pdf) (7 Dec, 10 Dec) 31 | * [Relation](notes/relation.pdf) (23 Nov, 30 Nov, 3 Dec) 32 | * [#Test 3](notes/test3.pdf) (19 Nov) 33 | * [Probability](notes/probability.pdf) (12 Nov, 17 Nov) 34 | * [Counting](notes/counting.pdf) (2 Nov, 5 Nov, 9 Nov) 35 | * [Halting Problem](notes/halting+problem.pdf) (29 Oct) 36 | * [#Test 2](notes/test2.pdf) (22 Oct) 37 | * [Recursion](notes/recursion.pdf) (19 Oct) 38 | * [Induction](notes/induction.pdf) (15 Oct) 39 | * [Algorithm](notes/algorithm.pdf) (12 Oct) 40 | * [Set Cardinality](notes/cardinality.pdf) (8 Oct) 41 | * [Sequence](notes/sequence.pdf) (5 Oct) 42 | * [Set and Function](notes/set+function.pdf) (28 Sep, 1 Oct) 43 | * [Puzzle Solving with SAT Solver](notes/prop+logic+solver.pdf) (24 Sep) 44 | - [nqueen-sat.c](assignments/nqueen-sat.c) 45 | * [#Test 1](notes/test1.pdf) (17 Sep) 46 | * [Proof](notes/proof.pdf) (14 Sep) 47 | * [Rule of Inference](notes/inference.pdf) (10 Sep) 48 | * [Predicate Logic](notes/predicate+logic.pdf) (7 Sep, 10 Sep) 49 | * [Propositional Logic](notes/propositional+logic.pdf) (3 Sep) 50 | * [Course Overview](notes/course+overview.pdf) (31 Aug) 51 | 52 | #### Assignments & Homework #### 53 | * Homework 4. Hasse Diagram Plotter 54 | - [homework description](assignments/homework4.pdf) 55 | - [report template](assignments/report.docx) 56 | - [ezdib library](assignments/ezdib) 57 | * Homework 3. Generating Languages from Grammars 58 | - [homework description](assignments/homework3.pdf) 59 | * Homework 2. Solving Puzzles with SAT Solver 60 | - [homework description](assignments/homework2.pdf) 61 | - [report template](assignments/report.docx) 62 | - [nqueen-sat.c](assignments/nqueen-sat.c) 63 | * Homework 1. Entrance Survey 64 | * Weekly reading group assignments [\[link\]](assignments/reading+group.md) 65 | - [Peer evaluation form](assignments/peer+evaluation.xlsx) 66 | 67 | #### Useful references 68 | - [Exam problems of the previous years](resource/) 69 | - [Foundations of Computer Science](http://infolab.stanford.edu/~ullman/focs.html), Stanford University 70 | - [Mathematics for Computer Science](https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-042j-mathematics-for-computer-science-spring-2015/), MIT OCW 71 | - [Discrete Mathematics: An Open Introduction, 3/e](http://discrete.openmathbooks.org/dmoi3.html) by Oscar Levin 72 | - [Programming and Mathematical Thinking: A Gentle Introduction to Discrete Math Featuring Python](http://webpages.math.luc.edu/~lauve/courses/215-fa2016/Stavely_python_ebook.pdf) by Allan M. Stavely 73 | 74 | ### Online channels ### 75 | * [Hisnet](http://hisnet.handong.edu) for attendance accounting and turning in homeworks 76 | * [GitHub repository](https://github.com/hongshin/DiscreteMath) for sharing lecture note, resource for homework, etc. 77 | * [Slack](https://hongshinclassroom.slack.com) for in-class interaction and instant messaging 78 | 79 | ### Previous instances ### 80 | * [ITP 20002 Discrete Mathematics (Shin Hong), 2020 Fall](https://github.com/hongshin/DiscreteMath/tree/2020fall) 81 | * [ITP 20002 Discrete Mathematics (Shin Hong), 2019 Fall](https://github.com/hongshin/DiscreteMath/tree/2019fall) 82 | * [ITP 20002 Discrete Mathematics (Shin Hong), 2018 Fall](https://github.com/hongshin/DiscreteMath/tree/18fall) 83 | -------------------------------------------------------------------------------- /assignments/book.md: -------------------------------------------------------------------------------- 1 | ### Book Reading Assignment (Optional) ### 2 | 3 | * Deadline: 11:59 PM, 26 Dec 2020 4 | * Submssion: via Hisnet-LMS 5 | * Format: at least 3 pages of A4 6 | * Credit: extra point in the final grading: upto 3 points. 7 | 8 | Read one of the recommended books (either Korean or English version) that *you have not read before* and then write an article that summaizes and discusses the topics of the book. 9 | Discussion includes new ideas, opinions and critiques related with the book. The recommended books are as follows: 10 | * 컴퓨터 과학이 여는 세상, 이광근 (Korean only) 11 | * Code: The Hidden Language of Computer Hardware and Software by Charles Petzold 12 | * Think Like A Programmer: An Introduction to Creative Problem Solving by V. Anton Spraul 13 | * Programming Pearls, 2/e by John Bentley (생각하는 프로그래밍) 14 | * Algorithms to Live By by Brian Christian and Tom Griffiths 15 | * Linked: How Everything Is Connected to Everything Else and What It Means for Business, Science and Everyday Life (링크: 21세기를 지배하는 네트워크 과학) 16 | * The Emperor's New Mind by Roger Penrose (황제의 새마음, 상/하) 17 | * Godel's Proof by Ernest Nagel et al., (괴델의 증명) 18 | * Godel, Escher, Bach: An Eternal Golden Braid by Douglas Hofstadter (괴델, 에셔, 바흐: 영원한 황금 노끈) 19 | 20 | You must read a book thoroughly before submission. Note that, as all for the other stuffs in this class, your article must be written in English. 21 | -------------------------------------------------------------------------------- /assignments/ezdib/LICENSE: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------ 2 | // Copyright (c) 1997 - 2012 3 | // Robert Umbehant 4 | // ezdib@wheresjames.com 5 | // http://www.wheresjames.com 6 | // 7 | // Redistribution and use in source and binary forms, with or 8 | // without modification, are permitted for commercial and 9 | // non-commercial purposes, provided that the following 10 | // conditions are met: 11 | // 12 | // * Redistributions of source code must retain the above copyright 13 | // notice, this list of conditions and the following disclaimer. 14 | // * The names of the developers or contributors may not be used to 15 | // endorse or promote products derived from this software without 16 | // specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 19 | // CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 20 | // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 | // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | //----------------------------------------------------------------*/ -------------------------------------------------------------------------------- /assignments/ezdib/Makefile: -------------------------------------------------------------------------------- 1 | 2 | default_target: all 3 | _END_ := 1 4 | 5 | #------------------------------------------------------------------- 6 | # Configure 7 | #------------------------------------------------------------------- 8 | 9 | OUTNAME := test_ezdib 10 | OUTTYPE := exe 11 | 12 | ifneq ($(findstring debug,$(TGT)),) 13 | CFG_DBG := 1 14 | endif 15 | 16 | ifneq ($(findstring windows,$(TGT)),) 17 | CFG_WIN := 1 18 | CFG_SYSTEM := windows 19 | else 20 | CFG_SYSTEM := posix 21 | endif 22 | 23 | ifneq ($(findstring static,$(TGT)),) 24 | CFG_STATIC := 1 25 | endif 26 | 27 | ifdef CFG_WIN 28 | PR := i586-mingw32msvc- 29 | endif 30 | 31 | #------------------------------------------------------------------- 32 | # Input / Output 33 | #------------------------------------------------------------------- 34 | 35 | # Create bin output path 36 | BINPATH := ../bin/$(CFG_SYSTEM) 37 | ifdef CFG_STATIC 38 | BINPATH := $(BINPATH)-static 39 | else 40 | BINPATH := $(BINPATH)-shared 41 | endif 42 | 43 | ifdef CFG_DBG 44 | BINPATH := $(BINPATH)-debug 45 | endif 46 | 47 | # Create intermediate file output path 48 | OBJPATH := $(BINPATH)/_obj/$(OUTNAME) 49 | 50 | # Output file 51 | ifdef CFG_WIN 52 | ifeq ($(OUTTYPE),dll) 53 | OUTFILE := $(BINPATH)/$(OUTNAME).dll 54 | else 55 | OUTFILE := $(BINPATH)/$(OUTNAME).exe 56 | endif 57 | else 58 | ifeq ($(OUTTYPE),dll) 59 | OUTFILE := $(BINPATH)/$(OUTNAME).so 60 | else 61 | OUTFILE := $(BINPATH)/$(OUTNAME) 62 | endif 63 | endif 64 | 65 | # Input files 66 | CCFILES := $(wildcard *.c) 67 | PPFILES := $(wildcard *.cpp) 68 | 69 | # Object files 70 | DEPENDS := $(foreach f,$(CCFILES),$(OBJPATH)/c/$(f:.c=.obj)) \ 71 | $(foreach f,$(PPFILES),$(OBJPATH)/cpp/$(f:.cpp=.obj)) 72 | 73 | #------------------------------------------------------------------- 74 | # Tools 75 | #------------------------------------------------------------------- 76 | 77 | # Paths tools 78 | RM := rm -f 79 | MD := mkdir -p 80 | 81 | # GCC 82 | PP := $(PR)g++ -c 83 | CC := $(PR)gcc -c 84 | LD := $(PR)g++ 85 | AR := $(PR)ar -cr 86 | RC := $(PR)windres 87 | 88 | PP_FLAGS := 89 | CC_FLAGS := 90 | LD_FLAGS := 91 | 92 | ifdef CFG_STATIC 93 | PP_FLAGS := $(PP_FLAGS) -static 94 | CC_FLAGS := $(CC_FLAGS) -static 95 | else 96 | PP_FLAGS := $(PP_FLAGS) -shared 97 | CC_FLAGS := $(CC_FLAGS) -shared 98 | endif 99 | 100 | ifeq ($(OUTTYPE),dll) 101 | LD_FLAGS := $(LD_FLAGS) -shared -module 102 | else 103 | ifdef CFG_STATIC 104 | LD_FLAGS := $(LD_FLAGS) -static 105 | endif 106 | endif 107 | 108 | ifndef CFG_WIN 109 | PP_FLAGS := $(PP_FLAGS) -fPIC 110 | CC_FLAGS := $(CC_FLAGS) -fPIC 111 | LD_FLAGS := $(LD_FLAGS) -fPIC 112 | endif 113 | 114 | ifdef CFG_DBG 115 | PP_FLAGS := $(PP_FLAGS) -g -DDEBUG -D_DEBUG 116 | CC_FLAGS := $(CC_FLAGS) -g -DDEBUG -D_DEBUG 117 | LD_FLAGS := $(LD_FLAGS) -g 118 | else 119 | PP_FLAGS := $(PP_FLAGS) -O2 120 | CC_FLAGS := $(CC_FLAGS) -O2 121 | endif 122 | 123 | 124 | #------------------------------------------------------------------- 125 | # Build 126 | #------------------------------------------------------------------- 127 | 128 | # Create 'c++' object file path 129 | $(OBJPATH)/cpp : 130 | - $(MD) $@ 131 | 132 | # Create 'c' object file path 133 | $(OBJPATH)/c : 134 | - $(MD) $@ 135 | 136 | # How to build a 'c++' file 137 | $(OBJPATH)/cpp/%.obj : %.cpp $(OBJPATH)/cpp 138 | $(PP) $< $(PP_FLAGS) -o $@ 139 | 140 | # How to build a 'c' file 141 | $(OBJPATH)/c/%.obj : %.c $(OBJPATH)/c 142 | $(CC) $< $(CC_FLAGS) -o $@ 143 | 144 | # Build the output 145 | $(OUTFILE) : $(DEPENDS) 146 | - $(RM) $@ 147 | $(LD) $(LD_FLAGS) $(DEPENDS) -o "$@" 148 | 149 | # Default target 150 | all : $(OUTFILE) 151 | 152 | clean : 153 | - $(RM) -R $(OBJPATH) 154 | 155 | rebuild : clean all 156 | -------------------------------------------------------------------------------- /assignments/ezdib/README: -------------------------------------------------------------------------------- 1 | 2 | To use this library, just copy ezdib.h and ezdib.c 3 | into your project and go! 4 | 5 | See main.c for examples. 6 | See ezdib.c for options you may want to customize 7 | 8 | //------------------------------------------------------------------ 9 | // Building the examples using make 10 | //------------------------------------------------------------------ 11 | 12 | // Linux / Mac / posix release 13 | make 14 | 15 | // Linux / Mac / posix debug 16 | make TGT=debug 17 | 18 | // Windows static release from linux or cygwin, 19 | // substitute your prefix for PR 20 | make TGT=windows-static PR=i686-pc-mingw32- 21 | 22 | // Windows static debug 23 | make TGT=windows-static-debug PR=i686-pc-mingw32- 24 | -------------------------------------------------------------------------------- /assignments/ezdib/ezdib.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------ 2 | // Copyright (c) 1997 - 2012 3 | // Robert Umbehant 4 | // ezdib@wheresjames.com 5 | // http://www.wheresjames.com 6 | // 7 | // Redistribution and use in source and binary forms, with or 8 | // without modification, are permitted for commercial and 9 | // non-commercial purposes, provided that the following 10 | // conditions are met: 11 | // 12 | // * Redistributions of source code must retain the above copyright 13 | // notice, this list of conditions and the following disclaimer. 14 | // * The names of the developers or contributors may not be used to 15 | // endorse or promote products derived from this software without 16 | // specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 19 | // CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 20 | // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 | // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | //----------------------------------------------------------------*/ 32 | 33 | #include "ezdib.h" 34 | 35 | //------------------------------------------------------------------ 36 | // Config 37 | //------------------------------------------------------------------ 38 | 39 | /// Enable static fonts 40 | /** 41 | This will prevent the creation of a font index, so font drawing 42 | will be slightly slower. Unless you are on a memory constrained 43 | system, you will probably prefer to leave this on. 44 | */ 45 | // #define EZD_STATIC_FONTS 46 | 47 | /// Define if you do not have string.h 48 | // #define EZD_NO_MEMCPY 49 | 50 | /// Define if you do not have malloc, calloc, and free, 51 | /** 52 | ezd_flood_file() will not work. 53 | */ 54 | // #define EZD_NO_ALLOCATION 55 | 56 | /// If you have no file handling routines 57 | /** 58 | ezd_save() will not work 59 | */ 60 | // #define EZD_NO_FILES 61 | 62 | /// If you do not have math.h. Sorry, you won't get circles 63 | /** 64 | ezd_circle() and ezd_arc() will not work 65 | */ 66 | // #define EZD_NO_MATH 67 | 68 | // Debugging 69 | #if defined( _DEBUG ) 70 | # define EZD_DEBUG 71 | #endif 72 | 73 | //------------------------------------------------------------------ 74 | // Internal config 75 | //------------------------------------------------------------------ 76 | 77 | #if !defined( EZD_NO_FILES ) 78 | # include 79 | #endif 80 | 81 | // malloc, calloc, free 82 | #if !defined( EZD_NO_ALLOCATION ) 83 | # if !defined( EZD_NO_STDLIB ) 84 | # include 85 | # else 86 | // No debug functions without stdlib 87 | # undef EZD_DEBUG 88 | # endif 89 | # if !defined( EZD_malloc ) 90 | # define EZD_malloc malloc 91 | # endif 92 | # if !defined( EZD_calloc ) 93 | # define EZD_calloc calloc 94 | # endif 95 | # if !defined( EZD_free ) 96 | # define EZD_free free 97 | # endif 98 | #else 99 | // Must use static fonts if no allocation routines 100 | # define EZD_STATIC_FONTS 101 | // Assume our debug functions won't work either 102 | # undef EZD_DEBUG 103 | #endif 104 | 105 | // sin(), cos() 106 | #if !defined( EZD_NO_MATH ) 107 | # include 108 | #endif 109 | 110 | // memcpy() and memset() substitutes 111 | #if defined( EZD_NO_MEMCPY ) 112 | # define EZD_MEMCPY ezd_memcpy 113 | # define EZD_MEMSET ezd_memset 114 | static void ezd_memcpy( char *pDst, const char *pSrc, int sz ) 115 | { while ( 0 < sz-- ) 116 | *(char*)pDst++ = *(char*)pSrc++; 117 | } 118 | static void ezd_memset( char *pDst, int v, int sz ) 119 | { while ( 0 < sz-- ) 120 | *(char*)pDst++ = (char)v; 121 | } 122 | #else 123 | # include 124 | # define EZD_MEMCPY memcpy 125 | # define EZD_MEMSET memset 126 | #endif 127 | 128 | #if defined( EZD_DEBUG ) 129 | # define _MSG( m ) printf( "\n%s(%d): %s() : %s\n", __FILE__, __LINE__, __FUNCTION__, m ) 130 | # define _SHOW( f, ... ) printf( "\n%s(%d): %s() : " f "\n", __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__ ) 131 | # define _ERR( r, m ) ( _MSG( m ), r ) 132 | #else 133 | # define _MSG( m ) 134 | # define _SHOW( ... ) 135 | # define _ERR( r, m ) ( r ) 136 | #endif 137 | 138 | //------------------------------------------------------------------ 139 | // Data structures 140 | //------------------------------------------------------------------ 141 | 142 | #if !defined( EZD_NOPACK ) 143 | # pragma pack( push, 1 ) 144 | #endif 145 | 146 | /// DIB file magic number 147 | #define EZD_MAGIC_NUMBER 0x4d42 148 | 149 | /// Header for a standard dib file (.bmp) 150 | typedef struct _SDIBFileHeader 151 | { 152 | /// Magic number, must be 0x42 0x4D (BM) 153 | unsigned short uMagicNumber; 154 | 155 | /// Size of the file in bytes 156 | unsigned int uSize; 157 | 158 | /// Reserved 159 | unsigned short uReserved1; 160 | 161 | /// Reserved 162 | unsigned short uReserved2; 163 | 164 | /// Offset to start of image data 165 | unsigned int uOffset; 166 | 167 | } SDIBFileHeader; 168 | 169 | /// Standard bitmap structure 170 | typedef struct _SBitmapInfoHeader 171 | { 172 | /// Size of this structure 173 | unsigned int biSize; 174 | 175 | /// Image width 176 | int biWidth; 177 | 178 | /// Image height 179 | int biHeight; 180 | 181 | /// Number of bit planes in the image 182 | unsigned short biPlanes; 183 | 184 | /// Bits per pixel / color depth 185 | unsigned short biBitCount; 186 | 187 | /// Type of compression used 188 | unsigned int biCompression; 189 | 190 | /// The total size of the image data 191 | unsigned int biSizeImage; 192 | 193 | /// Horizontal resolution in pixels per meter 194 | int biXPelsPerMeter; 195 | 196 | /// Vertical resolution in pixels per meter 197 | int biYPelsPerMeter; 198 | 199 | /// Total number of colors actually used in the image, 200 | /// zero for all colors used. 201 | unsigned int biClrUsed; 202 | 203 | /// Number of colors required for displaying the image, 204 | /// zero for all colors required. 205 | unsigned int biClrImportant; 206 | 207 | } SBitmapInfoHeader; 208 | 209 | # define EZD_FLAG_FREE_BUFFER 0x00010000 210 | 211 | // Returns non-zero if any color components are greater than the threshold 212 | # define EZD_COMPARE_THRESHOLD( c, t ) ( ( c & 0xff ) > t \ 213 | || ( ( c >> 8 ) & 0xff ) > t \ 214 | || ( ( c >> 16 ) & 0xff ) > t ) 215 | 216 | // This structure contains the memory image 217 | typedef struct _SImageData 218 | { 219 | /// Windows compatible image information 220 | SBitmapInfoHeader bih; 221 | 222 | /// Color palette for 1 bit images 223 | int colPalette[ 2 ]; 224 | 225 | /// Threshold color for 1 bit images 226 | int colThreshold; 227 | 228 | /// Image flags 229 | unsigned int uFlags; 230 | 231 | /// User set pixel callback function 232 | t_ezd_set_pixel pfSetPixel; 233 | 234 | /// User data passed to set pixel callback function 235 | void *pSetPixelUser; 236 | 237 | /// User image pointer 238 | unsigned char *pImage; 239 | 240 | /// Image data 241 | unsigned char pBuffer[ 4 ]; 242 | 243 | } SImageData; 244 | 245 | #if !defined( EZD_STATIC_FONTS ) 246 | 247 | // This structure contains the memory image 248 | typedef struct _SFontData 249 | { 250 | /// Font flags 251 | unsigned int uFlags; 252 | 253 | /// Font index pointers 254 | const unsigned char *pIndex[ 256 ]; 255 | 256 | /// Font bitmap data 257 | unsigned char pGlyph[ 1 ]; 258 | 259 | } SFontData; 260 | 261 | #endif 262 | 263 | #if !defined( EZD_NOPACK ) 264 | # pragma pack( pop ) 265 | #endif 266 | 267 | void ezd_destroy( HEZDIMAGE x_hDib ) 268 | { 269 | #if !defined( EZD_NO_ALLOCATION ) 270 | if ( x_hDib ) 271 | { SImageData *p = (SImageData*)x_hDib; 272 | if ( EZD_FLAG_FREE_BUFFER & p->uFlags ) 273 | EZD_free( (SImageData*)x_hDib ); 274 | } // end if 275 | #endif 276 | } 277 | 278 | int ezd_header_size() 279 | { 280 | return sizeof( SImageData ); 281 | } 282 | 283 | HEZDIMAGE ezd_initialize( void *x_pBuffer, int x_nBuffer, int x_lWidth, int x_lHeight, int x_lBpp, unsigned int x_uFlags ) 284 | { 285 | int nImageSize; 286 | SImageData *p; 287 | 288 | // Ensure the user buffer is acceptable 289 | if ( !x_pBuffer || ( 0 < x_nBuffer && sizeof( SImageData ) > x_nBuffer ) ) 290 | return _ERR( (HEZDIMAGE)0, "Invalid header buffer" ); 291 | 292 | // Sanity check 293 | if ( !x_lWidth || !x_lHeight ) 294 | return _ERR( (HEZDIMAGE)0, "Invalid parameters" ); 295 | 296 | // Calculate image size 297 | nImageSize = EZD_IMAGE_SIZE( x_lWidth, x_lHeight, x_lBpp, 4 ); 298 | if ( 0 >= nImageSize ) 299 | return _ERR( (HEZDIMAGE)0, "Invalid bits per pixel" ); 300 | 301 | // Point to users buffer 302 | p = (SImageData*)x_pBuffer; 303 | 304 | // Initialize the memory 305 | EZD_MEMSET( (char*)p, 0, sizeof( SImageData ) ); 306 | 307 | // Initialize image metrics 308 | p->bih.biSize = sizeof( SBitmapInfoHeader ); 309 | p->bih.biWidth = x_lWidth; 310 | p->bih.biHeight = x_lHeight; 311 | p->bih.biPlanes = 1; 312 | p->bih.biBitCount = x_lBpp; 313 | p->bih.biSizeImage = nImageSize; 314 | 315 | // Initialize color palette 316 | if ( 1 == x_lBpp ) 317 | { p->bih.biClrUsed = 2; 318 | p->bih.biClrImportant = 2; 319 | p->colPalette[ 0 ] = 0; 320 | p->colPalette[ 1 ] = 0xffffff; 321 | } // end if 322 | 323 | // Point image buffer 324 | p->pImage = ( EZD_FLAG_USER_IMAGE_BUFFER & x_uFlags ) ? 0 : p->pBuffer; 325 | 326 | // Save the flags 327 | p->uFlags = x_uFlags; 328 | 329 | return (HEZDIMAGE)p; 330 | } 331 | 332 | 333 | HEZDIMAGE ezd_create( int x_lWidth, int x_lHeight, int x_lBpp, unsigned int x_uFlags ) 334 | { 335 | #if defined( EZD_NO_ALLOCATION ) 336 | return 0; 337 | #else 338 | int nImageSize; 339 | SImageData *p; 340 | 341 | // Make sure the caller isn't stepping on our internal flags 342 | if ( 0xffff0000 & x_uFlags ) 343 | return _ERR( (HEZDIMAGE)0, "You have specified invalid flags" ); 344 | 345 | // Sanity check 346 | if ( !x_lWidth || !x_lHeight ) 347 | return _ERR( (HEZDIMAGE)0, "Invalid image width or height" ); 348 | 349 | // Calculate image size 350 | nImageSize = EZD_IMAGE_SIZE( x_lWidth, x_lHeight, x_lBpp, 4 ); 351 | if ( 0 >= nImageSize ) 352 | return _ERR( (HEZDIMAGE)0, "Invalid bits per pixel" ); 353 | 354 | // Allocate memory 355 | p = (SImageData*)EZD_malloc( sizeof( SImageData ) 356 | + ( ( EZD_FLAG_USER_IMAGE_BUFFER & x_uFlags ) ? 0 : nImageSize ) ); 357 | 358 | if ( !p ) 359 | return 0; 360 | 361 | // Initialize the header 362 | return ezd_initialize( p, sizeof( SImageData ), x_lWidth, x_lHeight, x_lBpp, x_uFlags | EZD_FLAG_FREE_BUFFER ); 363 | #endif 364 | } 365 | 366 | int ezd_set_image_buffer( HEZDIMAGE x_hDib, void *x_pImg, int x_nImg ) 367 | { 368 | SImageData *p = (SImageData*)x_hDib; 369 | if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize ) 370 | { _MSG( "Invalid parameters" ); return 0; } 371 | 372 | // Verify image buffer size if needed 373 | if ( x_pImg && 0 < x_nImg && x_nImg < (int)p->bih.biSizeImage ) 374 | { _MSG( "Invalid user image buffer size" ); return 0; } 375 | 376 | // Save user image pointer 377 | p->pImage = ( !x_pImg && !( EZD_FLAG_USER_IMAGE_BUFFER & p->uFlags ) ) 378 | ? p->pBuffer : x_pImg; 379 | return 1; 380 | } 381 | 382 | int ezd_set_pixel_callback( HEZDIMAGE x_hDib, t_ezd_set_pixel x_pf, void *x_pUser ) 383 | { 384 | SImageData *p = (SImageData*)x_hDib; 385 | if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize ) 386 | return _ERR( 0, "Invalid parameters" ); 387 | 388 | // Save user callback info 389 | p->pfSetPixel = x_pf; 390 | p->pSetPixelUser = x_pUser; 391 | 392 | return 1; 393 | } 394 | 395 | 396 | int ezd_set_palette_color( HEZDIMAGE x_hDib, int x_idx, int x_col ) 397 | { 398 | SImageData *p = (SImageData*)x_hDib; 399 | if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize ) 400 | return _ERR( 0, "Invalid parameters" ); 401 | 402 | if ( 0 > x_idx || 1 < x_idx ) 403 | return _ERR( 0, "Palette index out of range" ); 404 | 405 | // Set this palette color 406 | p->colPalette[ x_idx ] = x_col; 407 | 408 | return 1; 409 | } 410 | 411 | int ezd_get_palette_color( HEZDIMAGE x_hDib, int x_idx, int x_col ) 412 | { 413 | SImageData *p = (SImageData*)x_hDib; 414 | if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize ) 415 | return _ERR( 0, "Invalid parameters" ); 416 | 417 | if ( 0 > x_idx || 1 < x_idx ) 418 | return _ERR( 0, "Palette index out of range" ); 419 | 420 | // Return this palette color 421 | return p->colPalette[ x_idx ]; 422 | } 423 | 424 | int* ezd_get_palette( HEZDIMAGE x_hDib ) 425 | { 426 | SImageData *p = (SImageData*)x_hDib; 427 | if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize ) 428 | return _ERR( (int*)0, "Invalid parameters" ); 429 | 430 | // Return a pointer to the palette 431 | return p->colPalette; 432 | } 433 | 434 | int ezd_get_palette_size( HEZDIMAGE x_hDib ) 435 | { 436 | SImageData *p = (SImageData*)x_hDib; 437 | if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize ) 438 | return _ERR( 0, "Invalid parameters" ); 439 | 440 | switch( p->bih.biBitCount ) 441 | { 442 | case 1 : 443 | return 2; 444 | } // end switch 445 | 446 | return 0; 447 | } 448 | 449 | int ezd_set_color_threshold( HEZDIMAGE x_hDib, int x_col ) 450 | { 451 | SImageData *p = (SImageData*)x_hDib; 452 | if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize ) 453 | return _ERR( 0, "Invalid parameters" ); 454 | 455 | // Calculate scan width 456 | p->colThreshold = x_col; 457 | 458 | return 1; 459 | } 460 | 461 | int ezd_get_width( HEZDIMAGE x_hDib ) 462 | { 463 | SImageData *p = (SImageData*)x_hDib; 464 | if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize ) 465 | return _ERR( 0, "Invalid parameters" ); 466 | 467 | // Calculate scan width 468 | return p->bih.biWidth; 469 | } 470 | 471 | int ezd_get_height( HEZDIMAGE x_hDib ) 472 | { 473 | SImageData *p = (SImageData*)x_hDib; 474 | if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize ) 475 | return _ERR( 0, "Invalid parameters" ); 476 | 477 | // Calculate scan width 478 | return p->bih.biHeight; 479 | } 480 | 481 | int ezd_get_bpp( HEZDIMAGE x_hDib ) 482 | { 483 | SImageData *p = (SImageData*)x_hDib; 484 | if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize ) 485 | return _ERR( 0, "Invalid parameters" ); 486 | 487 | // Calculate scan width 488 | return p->bih.biBitCount; 489 | } 490 | 491 | int ezd_get_image_size( HEZDIMAGE x_hDib ) 492 | { 493 | SImageData *p = (SImageData*)x_hDib; 494 | if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize ) 495 | return _ERR( 0, "Invalid parameters" ); 496 | 497 | // Calculate scan width 498 | return p->bih.biSizeImage; 499 | } 500 | 501 | 502 | void* ezd_get_image_ptr( HEZDIMAGE x_hDib ) 503 | { 504 | SImageData *p = (SImageData*)x_hDib; 505 | if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize ) 506 | return _ERR( (void*)0, "Invalid parameters" ); 507 | 508 | // Calculate scan width 509 | return p->pImage; 510 | } 511 | 512 | 513 | int ezd_save( HEZDIMAGE x_hDib, const char *x_pFile ) 514 | { 515 | #if defined( EZD_NO_FILES ) 516 | return 0; 517 | #else 518 | FILE *fh; 519 | int palette_size = 0; 520 | SDIBFileHeader dfh; 521 | SImageData *p = (SImageData*)x_hDib; 522 | 523 | // Sanity checks 524 | if ( !x_pFile || !*x_pFile || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize || !p->pImage ) 525 | return _ERR( 0, "Invalid parameters" ); 526 | 527 | // Ensure packing is ok 528 | if ( sizeof( SDIBFileHeader ) != 14 ) 529 | return _ERR( 0, "Structure packing for DIB header is incorrect" ); 530 | 531 | // Ensure packing is ok 532 | if ( sizeof( SBitmapInfoHeader ) != 40 ) 533 | return _ERR( 0, "Structure packing for BITMAP header is incorrect" ); 534 | 535 | // Add palettte size 536 | if ( 1 == p->bih.biBitCount ) 537 | palette_size = sizeof( p->colPalette[ 0 ] ) * 2; 538 | 539 | // Attempt to open the output file 540 | fh = fopen ( x_pFile, "wb" ); 541 | if ( !fh ) 542 | return _ERR( 0, "Failed to open DIB file for writing" ); 543 | 544 | // Fill in header info 545 | dfh.uMagicNumber = EZD_MAGIC_NUMBER; 546 | dfh.uSize = sizeof( SDIBFileHeader ) + p->bih.biSize + p->bih.biSizeImage; 547 | dfh.uReserved1 = 0; 548 | dfh.uReserved2 = 0; 549 | dfh.uOffset = sizeof( SDIBFileHeader ) + p->bih.biSize + palette_size; 550 | 551 | // Write the header 552 | if ( sizeof( dfh ) != fwrite( &dfh, 1, sizeof( dfh ), fh ) ) 553 | { fclose( fh ); return _ERR( 0, "Error writing DIB header" ); } 554 | 555 | // Write the Bitmap header 556 | if ( p->bih.biSize != fwrite( &p->bih, 1, p->bih.biSize, fh ) ) 557 | { fclose( fh ); return _ERR( 0, "Error writing bitmap header" ); } 558 | 559 | // Write the color palette if needed 560 | if ( 0 < palette_size ) 561 | if ( sizeof( p->colPalette ) != fwrite( p->colPalette, 1, palette_size, fh ) ) 562 | { fclose( fh ); return _ERR( 0, "Error writing palette" ); } 563 | 564 | // Write the Image data 565 | if ( p->bih.biSizeImage != fwrite( p->pImage, 1, p->bih.biSizeImage, fh ) ) 566 | { fclose( fh ); return _ERR( 0, "Error writing image data" ); } 567 | 568 | // Close the file handle 569 | fclose( fh ); 570 | 571 | return 1; 572 | #endif 573 | } 574 | 575 | int ezd_fill( HEZDIMAGE x_hDib, int x_col ) 576 | { 577 | int w, h, sw, pw, x, y; 578 | SImageData *p = (SImageData*)x_hDib; 579 | 580 | if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize 581 | || ( !p->pImage && !p->pfSetPixel ) ) 582 | return _ERR( 0, "Invalid parameters" ); 583 | 584 | // Calculate image metrics 585 | w = EZD_ABS( p->bih.biWidth ); 586 | h = EZD_ABS( p->bih.biHeight ); 587 | 588 | // Check for user callback function 589 | if ( p->pfSetPixel ) 590 | { 591 | // Fill each pixel 592 | for ( y = 0; y < h; y++ ) 593 | for( x = 0; x < w; x++ ) 594 | if ( !p->pfSetPixel( p->pSetPixelUser, x, y, x_col, 0 ) ) 595 | return 0; 596 | 597 | return 1; 598 | 599 | } // end if 600 | 601 | // Pixel and scan widths 602 | pw = EZD_FITTO( p->bih.biBitCount, 8 ); 603 | sw = EZD_SCANWIDTH( w, p->bih.biBitCount, 4 ); 604 | 605 | // Set the first line 606 | switch( p->bih.biBitCount ) 607 | { 608 | case 1 : 609 | EZD_MEMSET( p->pImage, EZD_COMPARE_THRESHOLD( x_col, p->colThreshold ) ? 0xff : 0, sw ); 610 | break; 611 | 612 | case 24 : 613 | { 614 | // Color values 615 | unsigned char r = x_col & 0xff; 616 | unsigned char g = ( x_col >> 8 ) & 0xff; 617 | unsigned char b = ( x_col >> 16 ) & 0xff; 618 | unsigned char *pImg = p->pImage; 619 | 620 | // Set the first line 621 | for( x = 0; x < w; x++, pImg += pw ) 622 | pImg[ 0 ] = r, pImg[ 1 ] = g, pImg[ 2 ] = b; 623 | 624 | } break; 625 | 626 | case 32 : 627 | { 628 | // Set the first line 629 | int *pImg = (int*)p->pImage; 630 | for( x = 0; x < w; x++, pImg++ ) 631 | *pImg = x_col; 632 | 633 | } break; 634 | 635 | default : 636 | return 0; 637 | 638 | } // end switch 639 | 640 | // Copy remaining lines 641 | for( y = 1; y < h; y++ ) 642 | EZD_MEMCPY( &p->pImage[ y * sw ], p->pImage, sw ); 643 | 644 | return 1; 645 | } 646 | 647 | int ezd_set_pixel( HEZDIMAGE x_hDib, int x, int y, int x_col ) 648 | { 649 | int w, h, sw, pw; 650 | SImageData *p = (SImageData*)x_hDib; 651 | 652 | if ( !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize 653 | || ( !p->pImage && !p->pfSetPixel ) ) 654 | return _ERR( 0, "Invalid parameters" ); 655 | 656 | // Calculate image metrics 657 | w = EZD_ABS( p->bih.biWidth ); 658 | h = EZD_ABS( p->bih.biHeight ); 659 | 660 | // Ensure pixel is within the image 661 | if ( 0 > x || x >= w || 0 > y || y >= h ) 662 | { _SHOW( "Point out of range : %d,%d : %dx%d ", x, y, w, h ); 663 | return 0; 664 | } // en dif 665 | 666 | // Set the specified pixel 667 | if ( p->pfSetPixel ) 668 | return p->pfSetPixel( p->pSetPixelUser, x, y, x_col, 0 ); 669 | 670 | // Pixel and scan width 671 | pw = EZD_FITTO( p->bih.biBitCount, 8 ); 672 | sw = EZD_SCANWIDTH( w, p->bih.biBitCount, 4 ); 673 | 674 | // Set the first line 675 | switch( p->bih.biBitCount ) 676 | { 677 | case 1 : 678 | p->pImage[ y * sw + ( x >> 3 ) ] |= 0x80 >> ( x & 7 ); 679 | break; 680 | 681 | case 24 : 682 | { 683 | // Color values 684 | unsigned char r = x_col & 0xff; 685 | unsigned char g = ( x_col >> 8 ) & 0xff; 686 | unsigned char b = ( x_col >> 16 ) & 0xff; 687 | unsigned char *pImg = &p->pImage[ y * sw + x * pw ]; 688 | 689 | // Set the pixel color 690 | pImg[ 0 ] = r, pImg[ 1 ] = g, pImg[ 2 ] = b; 691 | 692 | } break; 693 | 694 | case 32 : 695 | *(unsigned int*)&p->pImage[ y * sw + x * pw ] = x_col; 696 | break; 697 | 698 | default : 699 | return 0; 700 | 701 | } // end switch 702 | 703 | return 1; 704 | } 705 | 706 | int ezd_get_pixel( HEZDIMAGE x_hDib, int x, int y ) 707 | { 708 | int w, h, sw, pw; 709 | SImageData *p = (SImageData*)x_hDib; 710 | 711 | if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize || !p->pImage ) 712 | return _ERR( 0, "Invalid parameters" ); 713 | 714 | // Calculate image metrics 715 | w = EZD_ABS( p->bih.biWidth ); 716 | h = EZD_ABS( p->bih.biHeight ); 717 | 718 | // Ensure pixel is within the image 719 | if ( 0 > x || x >= w || 0 > y || y >= h ) 720 | { _SHOW( "Point out of range : %d,%d : %dx%d ", x, y, w, h ); 721 | return 0; 722 | } // en dif 723 | 724 | // Pixel and scan width 725 | pw = EZD_FITTO( p->bih.biBitCount, 8 ); 726 | sw = EZD_SCANWIDTH( w, p->bih.biBitCount, 4 ); 727 | 728 | // Set the first line 729 | switch( p->bih.biBitCount ) 730 | { 731 | case 1 : 732 | return p->colPalette[ ( p->pImage[ y * sw + ( x >> 3 ) ] & ( 0x80 >> ( x & 7 ) ) ) ? 1 : 0 ]; 733 | 734 | case 24 : 735 | { 736 | // Return the color of the specified pixel 737 | unsigned char *pImg = &p->pImage[ y * sw + x * pw ]; 738 | return pImg[ 0 ] | ( pImg[ 1 ] << 8 ) | ( pImg[ 2 ] << 16 ); 739 | 740 | } break; 741 | 742 | case 32 : 743 | return *(unsigned int*)&p->pImage[ y * sw + x * pw ]; 744 | 745 | } // end switch 746 | 747 | return 0; 748 | } 749 | 750 | int ezd_line( HEZDIMAGE x_hDib, int x1, int y1, int x2, int y2, int x_col ) 751 | { 752 | int w, h, sw, pw, xd, yd, xl, yl, done = 0; 753 | SImageData *p = (SImageData*)x_hDib; 754 | 755 | if ( !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize 756 | || ( !p->pImage && !p->pfSetPixel ) ) 757 | return _ERR( 0, "Invalid parameters" ); 758 | 759 | // Calculate image metrics 760 | w = EZD_ABS( p->bih.biWidth ); 761 | h = EZD_ABS( p->bih.biHeight ); 762 | 763 | // Determine direction and distance 764 | xd = ( x1 < x2 ) ? 1 : -1; 765 | yd = ( y1 < y2 ) ? 1 : -1; 766 | xl = ( x1 < x2 ) ? ( x2 - x1 ) : ( x1 - x2 ); 767 | yl = ( y1 < y2 ) ? ( y2 - y1 ) : ( y1 - y2 ); 768 | 769 | // Check for user callback function 770 | if ( p->pfSetPixel ) 771 | { 772 | int mx = 0, my = 0, c = EZD_COMPARE_THRESHOLD( x_col, p->colThreshold ); 773 | static unsigned char xm[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; 774 | 775 | // Draw the line 776 | while ( !done ) 777 | { 778 | if ( x1 == x2 && y1 == y2 ) 779 | done = 1; 780 | 781 | // Plot pixel 782 | if ( 0 <= x1 && x1 < w && 0 <= y1 && y1 < h ) 783 | if ( !p->pfSetPixel( p->pSetPixelUser, x1, y1, x_col, 0 ) ) 784 | return 0; 785 | 786 | mx += xl; 787 | if ( x1 != x2 && mx > yl ) 788 | x1 += xd, mx -= yl; 789 | 790 | my += yl; 791 | if ( y1 != y2 && my > xl ) 792 | y1 += yd, my -= xl; 793 | 794 | } // end while 795 | 796 | return 1; 797 | 798 | } // end if 799 | 800 | // Pixel and scan width 801 | pw = EZD_FITTO( p->bih.biBitCount, 8 ); 802 | sw = EZD_SCANWIDTH( w, p->bih.biBitCount, 4 ); 803 | 804 | // Set the first line 805 | switch( p->bih.biBitCount ) 806 | { 807 | case 1 : 808 | { 809 | int mx = 0, my = 0, c = EZD_COMPARE_THRESHOLD( x_col, p->colThreshold ); 810 | static unsigned char xm[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; 811 | 812 | // Draw the line 813 | while ( !done ) 814 | { 815 | if ( x1 == x2 && y1 == y2 ) 816 | done = 1; 817 | 818 | // Plot pixel 819 | if ( 0 <= x1 && x1 < w && 0 <= y1 && y1 < h ) 820 | if ( c ) 821 | p->pImage[ y1 * sw + ( x1 >> 3 ) ] |= xm[ x1 & 7 ]; 822 | else 823 | p->pImage[ y1 * sw + ( x1 >> 3 ) ] &= ~xm[ x1 & 7 ]; 824 | 825 | mx += xl; 826 | if ( x1 != x2 && mx > yl ) 827 | x1 += xd, mx -= yl; 828 | 829 | my += yl; 830 | if ( y1 != y2 && my > xl ) 831 | y1 += yd, my -= xl; 832 | 833 | } // end while 834 | 835 | } break; 836 | 837 | case 24 : 838 | { 839 | // Color values 840 | unsigned char r = x_col & 0xff; 841 | unsigned char g = ( x_col >> 8 ) & 0xff; 842 | unsigned char b = ( x_col >> 16 ) & 0xff; 843 | unsigned char *pImg; 844 | int mx = 0, my = 0; 845 | 846 | while ( !done ) 847 | { 848 | if ( x1 == x2 && y1 == y2 ) 849 | done = 1; 850 | 851 | // Plot pixel 852 | if ( 0 <= x1 && x1 < w && 0 <= y1 && y1 < h ) 853 | { pImg = &p->pImage[ y1 * sw + x1 * pw ]; 854 | pImg[ 0 ] = r, pImg[ 1 ] = g, pImg[ 2 ] = b; 855 | } // end if 856 | 857 | mx += xl; 858 | if ( x1 != x2 && mx > yl ) 859 | x1 += xd, mx -= yl; 860 | 861 | my += yl; 862 | if ( y1 != y2 && my > xl ) 863 | y1 += yd, my -= xl; 864 | 865 | } // end while 866 | 867 | } break; 868 | 869 | case 32 : 870 | { 871 | // Color values 872 | int mx = 0, my = 0; 873 | 874 | // Draw the line 875 | while ( !done ) 876 | { 877 | if ( x1 == x2 && y1 == y2 ) 878 | done = 1; 879 | 880 | // Plot pixel 881 | if ( 0 <= x1 && x1 < w && 0 <= y1 && y1 < h ) 882 | *(unsigned int*)&p->pImage[ y1 * sw + x1 * pw ] = x_col; 883 | 884 | mx += xl; 885 | if ( x1 != x2 && mx > yl ) 886 | x1 += xd, mx -= yl; 887 | 888 | my += yl; 889 | if ( y1 != y2 && my > xl ) 890 | y1 += yd, my -= xl; 891 | 892 | } // end while 893 | 894 | } break; 895 | 896 | default : 897 | return 0; 898 | 899 | } // end switch 900 | 901 | return 1; 902 | } 903 | 904 | int ezd_rect( HEZDIMAGE x_hDib, int x1, int y1, int x2, int y2, int x_col ) 905 | { 906 | // Draw rectangle 907 | return ezd_line( x_hDib, x1, y1, x2, y1, x_col ) 908 | && ezd_line( x_hDib, x2, y1, x2, y2, x_col ) 909 | && ezd_line( x_hDib, x2, y2, x1, y2, x_col ) 910 | && ezd_line( x_hDib, x1, y2, x1, y1, x_col ); 911 | } 912 | 913 | #define EZD_PI ( (double)3.141592654 ) 914 | #define EZD_PI2 ( EZD_PI * (double)2 ) 915 | #define EZD_PI4 ( EZD_PI * (double)4 ) 916 | 917 | int ezd_arc( HEZDIMAGE x_hDib, int x, int y, int x_rad, double x_dStart, double x_dEnd, int x_col ) 918 | { 919 | #if defined( EZD_NO_MATH ) 920 | return 0; 921 | #else 922 | double arc; 923 | int i, w, h, sw, pw, px, py; 924 | int res = (int)( (double)x_rad * EZD_PI4 ), resdraw; 925 | unsigned char *pImg; 926 | SImageData *p = (SImageData*)x_hDib; 927 | 928 | if ( !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize 929 | || ( !p->pImage && !p->pfSetPixel ) ) 930 | return _ERR( 0, "Invalid parameters" ); 931 | 932 | // Dont' draw null arc 933 | if ( x_dStart == x_dEnd ) 934 | return 1; 935 | 936 | // Ensure correct order 937 | else if ( x_dStart > x_dEnd ) 938 | { double t = x_dStart; 939 | x_dStart = x_dEnd; 940 | x_dEnd = t; 941 | } // end if 942 | 943 | // Get arc size 944 | arc = x_dEnd - x_dStart; 945 | 946 | // How many points to draw 947 | resdraw = ( EZD_PI2 <= arc ) ? res : (int)( arc * (double)res / EZD_PI2 ); 948 | 949 | // Calculate image metrics 950 | w = EZD_ABS( p->bih.biWidth ); 951 | h = EZD_ABS( p->bih.biHeight ); 952 | 953 | // Ensure pixel is within the image 954 | if ( 0 > x || x >= w || 0 > y || y >= h ) 955 | { _SHOW( "Point out of range : %d,%d : %dx%d ", x, y, w, h ); 956 | return 0; 957 | } // en dif 958 | 959 | // Check for user callback function 960 | if ( p->pfSetPixel ) 961 | { 962 | // Draw the circle 963 | for ( i = 0; i < resdraw; i++ ) 964 | { 965 | // Offset for this pixel 966 | px = x + (int)( (double)x_rad * cos( x_dStart + (double)i * EZD_PI2 / (double)res ) ); 967 | py = y + (int)( (double)x_rad * sin( x_dStart + (double)i * EZD_PI2 / (double)res ) ); 968 | 969 | // Plot pixel 970 | if ( 0 <= px && px < w && 0 <= py && py < h ) 971 | if ( !p->pfSetPixel( p->pSetPixelUser, px, py, x_col, 0 ) ) 972 | return 0; 973 | 974 | } // end while 975 | 976 | return 1; 977 | 978 | } // end if 979 | 980 | // Pixel and scan width 981 | pw = EZD_FITTO( p->bih.biBitCount, 8 ); 982 | sw = EZD_SCANWIDTH( w, p->bih.biBitCount, 4 ); 983 | 984 | switch( p->bih.biBitCount ) 985 | { 986 | case 1: 987 | { 988 | int c = EZD_COMPARE_THRESHOLD( x_col, p->colThreshold ); 989 | static unsigned char xm[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; 990 | 991 | // Draw the circle 992 | for ( i = 0; i < resdraw; i++ ) 993 | { 994 | // Offset for this pixel 995 | px = x + (int)( (double)x_rad * cos( x_dStart + (double)i * EZD_PI2 / (double)res ) ); 996 | py = y + (int)( (double)x_rad * sin( x_dStart + (double)i * EZD_PI2 / (double)res ) ); 997 | 998 | // Plot pixel 999 | if ( 0 <= px && px < w && 0 <= py && py < h ) 1000 | if ( c ) 1001 | p->pImage[ py * sw + ( px >> 3 ) ] |= xm[ px & 7 ]; 1002 | else 1003 | p->pImage[ py * sw + ( px >> 3 ) ] &= ~xm[ px & 7 ]; 1004 | 1005 | } // end while 1006 | 1007 | } break; 1008 | 1009 | case 24 : 1010 | { 1011 | // Color values 1012 | unsigned char r = x_col & 0xff; 1013 | unsigned char g = ( x_col >> 8 ) & 0xff; 1014 | unsigned char b = ( x_col >> 16 ) & 0xff; 1015 | for ( i = 0; i < resdraw; i++ ) 1016 | { 1017 | // Offset for this pixel 1018 | px = x + (int)( (double)x_rad * cos( x_dStart + (double)i * EZD_PI2 / (double)res ) ); 1019 | py = y + (int)( (double)x_rad * sin( x_dStart + (double)i * EZD_PI2 / (double)res ) ); 1020 | 1021 | // If it falls on the image 1022 | if ( 0 <= px && px < w && 0 <= py && py < h ) 1023 | { pImg = &p->pImage[ py * sw + px * pw ]; 1024 | pImg[ 0 ] = r, pImg[ 1 ] = g, pImg[ 2 ] = b; 1025 | } // end if 1026 | 1027 | } // end for 1028 | 1029 | } break; 1030 | 1031 | case 32 : 1032 | for ( i = 0; i < resdraw; i++ ) 1033 | { 1034 | // Offset for this pixel 1035 | px = x + (int)( (double)x_rad * sin( (double)i * EZD_PI2 / (double)res ) ); 1036 | py = y + (int)( (double)x_rad * cos( (double)i * EZD_PI2 / (double)res ) ); 1037 | 1038 | // If it falls on the image 1039 | if ( 0 <= px && px < w && 0 <= py && py < h ) 1040 | *(unsigned int*)&p->pImage[ py * sw + px * pw ] = x_col; 1041 | 1042 | } // end for 1043 | 1044 | break; 1045 | 1046 | default : 1047 | return 0; 1048 | 1049 | } // end switch 1050 | 1051 | return 1; 1052 | #endif 1053 | } 1054 | 1055 | 1056 | int ezd_circle( HEZDIMAGE x_hDib, int x, int y, int x_rad, int x_col ) 1057 | { 1058 | return ezd_arc( x_hDib, x, y, x_rad, 0, EZD_PI2, x_col ); 1059 | } 1060 | 1061 | int ezd_fill_rect( HEZDIMAGE x_hDib, int x1, int y1, int x2, int y2, int x_col ) 1062 | { 1063 | int w, h, x, y, sw, pw, fw, fh; 1064 | unsigned char *pStart, *pPos; 1065 | SImageData *p = (SImageData*)x_hDib; 1066 | 1067 | if ( !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize 1068 | || ( !p->pImage && !p->pfSetPixel ) ) 1069 | return _ERR( 0, "Invalid parameters" ); 1070 | 1071 | // Calculate image metrics 1072 | w = EZD_ABS( p->bih.biWidth ); 1073 | h = EZD_ABS( p->bih.biHeight ); 1074 | 1075 | // Swap coords if needed 1076 | if ( x1 > x2 ) { int t = x1; x1 = x2; x2 = t; } 1077 | if ( y1 > y2 ) { int t = y1; y1 = y2; y2 = t; } 1078 | 1079 | // Clip 1080 | if ( 0 > x1 ) x1 = 0; else if ( x1 >= w ) x1 = w - 1; 1081 | if ( 0 > y1 ) y1 = 0; else if ( y1 >= h ) y1 = h - 1; 1082 | if ( 0 > x2 ) x2 = 0; else if ( x2 >= w ) x2 = w - 1; 1083 | if ( 0 > y2 ) y2 = 0; else if ( y2 >= h ) y2 = h - 1; 1084 | 1085 | // Fill width and height 1086 | fw = x2 - x1; 1087 | fh = y2 - y1; 1088 | 1089 | // Are we left with a valid region 1090 | if ( 0 > fw || 0 > fh ) 1091 | { _SHOW( "Invalid fill rect : %d,%d -> %d,%d : %dx%d ", 1092 | x1, y1, x2, y2, w, h ); 1093 | return 0; 1094 | } // en dif 1095 | 1096 | // Check for user callback function 1097 | if ( p->pfSetPixel ) 1098 | { 1099 | // Fill each pixel 1100 | for ( y = y1; y < y2; y++ ) 1101 | for( x = x1; x < x2; x++ ) 1102 | if ( 0 <= x && x < w && 0 <= y && y < h ) 1103 | if ( !p->pfSetPixel( p->pSetPixelUser, x, y, x_col, 0 ) ) 1104 | return 0; 1105 | 1106 | return 1; 1107 | 1108 | } // end if 1109 | 1110 | // Pixel and scan width 1111 | pw = EZD_FITTO( p->bih.biBitCount, 8 ); 1112 | sw = EZD_SCANWIDTH( w, p->bih.biBitCount, 1 ); 1113 | 1114 | // Set the first line 1115 | switch( p->bih.biBitCount ) 1116 | { 1117 | case 1 : 1118 | { 1119 | int c = EZD_COMPARE_THRESHOLD( x_col, p->colThreshold ); 1120 | static unsigned char xm[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; 1121 | 1122 | // Just fill it in pixel by pixel for 1 bit images 1123 | for ( y = y1; y < y2; y++ ) 1124 | for( x = x1; x < x2; x++ ) 1125 | if ( 0 <= x && x < w && 0 <= y && y < h ) 1126 | if ( c ) 1127 | p->pImage[ y * sw + ( x >> 3 ) ] |= xm[ x & 7 ]; 1128 | else 1129 | p->pImage[ y * sw + ( x >> 3 ) ] &= ~xm[ x & 7 ]; 1130 | 1131 | return 1; 1132 | 1133 | } break; 1134 | 1135 | case 24 : 1136 | { 1137 | // Color values 1138 | unsigned char r = x_col & 0xff; 1139 | unsigned char g = ( x_col >> 8 ) & 0xff; 1140 | unsigned char b = ( x_col >> 16 ) & 0xff; 1141 | pStart = pPos = &p->pImage[ y1 * sw + x1 * pw ]; 1142 | 1143 | // Set the first line 1144 | for( x = 0; x < fw; x++, pPos += pw ) 1145 | pPos[ 0 ] = r, pPos[ 1 ] = g, pPos[ 2 ] = b; 1146 | 1147 | } break; 1148 | 1149 | case 32 : 1150 | { 1151 | // Set the first line 1152 | pStart = pPos = &p->pImage[ y1 * sw + x1 * pw ]; 1153 | for( x = 0; x < fw; x++, pPos += pw ) 1154 | *(unsigned int*)pPos = x_col; 1155 | 1156 | } break; 1157 | 1158 | default : 1159 | return 0; 1160 | 1161 | } // end switch 1162 | 1163 | // Copy remaining lines 1164 | pPos = pStart; 1165 | for( y = 1; y < fh; y++ ) 1166 | { 1167 | // Skip to next line 1168 | pPos += sw; 1169 | EZD_MEMCPY( pPos, pStart, fw * pw ); 1170 | 1171 | } // end for 1172 | 1173 | return 1; 1174 | } 1175 | 1176 | int ezd_flood_fill( HEZDIMAGE x_hDib, int x, int y, int x_bcol, int x_col ) 1177 | { 1178 | #if defined( EZD_NO_ALLOCATION ) 1179 | return 0; 1180 | #else 1181 | int ok, n, i, ii, w, h, sw, pw, bc; 1182 | unsigned char r, g, b, br, bg, bb; 1183 | unsigned char *pImg, *map; 1184 | SImageData *p = (SImageData*)x_hDib; 1185 | 1186 | if ( !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize || !p->pImage ) 1187 | return _ERR( 0, "Invalid parameters" ); 1188 | 1189 | // +++ Fix ezd_flood_fill() for 1 bpp 1190 | if ( 1 == p->bih.biBitCount ) 1191 | return 0; // _ERR( 0, "Invalid pixel depth" ); 1192 | 1193 | // Calculate image metrics 1194 | w = EZD_ABS( p->bih.biWidth ); 1195 | h = EZD_ABS( p->bih.biHeight ); 1196 | 1197 | // Ensure pixel is within the image 1198 | if ( 0 > x || x >= w || 0 > y || y >= h ) 1199 | { _SHOW( "Point out of range : %d,%d : %dx%d ", x, y, w, h ); 1200 | return 0; 1201 | } // en dif 1202 | 1203 | // Pixel and scan width 1204 | pw = EZD_FITTO( p->bih.biBitCount, 8 ); 1205 | sw = EZD_SCANWIDTH( w, p->bih.biBitCount, 4 ); 1206 | 1207 | // Set the image pointer 1208 | pImg = p->pImage; 1209 | 1210 | // Allocate space for fill map 1211 | map = (unsigned char*)EZD_calloc( w * h, 1 ); 1212 | if ( !map ) 1213 | return 0; 1214 | 1215 | // Prepare 24 bit color components 1216 | r = x_col & 0xff; g = ( x_col >> 8 ) & 0xff; b = ( x_col >> 16 ) & 0xff; 1217 | br = x_bcol & 0xff; bg = ( x_bcol >> 8 ) & 0xff; bb = ( x_bcol >> 16 ) & 0xff; 1218 | 1219 | // Initialize indexes 1220 | i = y * w + x; 1221 | ii = y * sw + x * pw; 1222 | 1223 | // Save away bit count 1224 | bc = p->bih.biBitCount; 1225 | 1226 | // Crawl the map 1227 | while ( ( map[ i ] & 0x0f ) <= 3 ) 1228 | { 1229 | 1230 | if ( ( map[ i ] & 0x0f ) == 0 ) 1231 | { 1232 | // In the name of simplicity 1233 | switch( bc ) 1234 | { 1235 | case 24 : 1236 | pImg[ ii ] = r; 1237 | pImg[ ii + 1 ] = g; 1238 | pImg[ ii + 2 ] = b; 1239 | break; 1240 | 1241 | case 32 : 1242 | *(unsigned int*)&p->pImage[ ii ] = x_col; 1243 | break; 1244 | 1245 | } // end switch 1246 | 1247 | // Point to next direction 1248 | map[ i ] &= 0xf0, map[ i ] |= 1; 1249 | 1250 | // Can we go up? 1251 | if ( y < ( h - 1 ) ) 1252 | { 1253 | n = ( y + 1 ) * sw + x * pw; 1254 | switch( bc ) 1255 | { case 24 : 1256 | ok = pImg[ n ] != r || pImg[ n + 1 ] != g || pImg[ n + 2 ] != b; 1257 | if ( ok ) ok = pImg[ n ] != br || pImg[ n + 1 ] != bg || pImg[ n + 2 ] != bb; 1258 | break; 1259 | case 32 : 1260 | ok = *(unsigned int*)&pImg[ n ] != x_col; 1261 | if ( ok ) ok = *(unsigned int*)&pImg[ n ] != x_bcol; 1262 | break; 1263 | } // end switch 1264 | 1265 | if ( ok ) 1266 | { y++; 1267 | i = y * w + x; 1268 | map[ i ] = 0x10; 1269 | ii = n; 1270 | } // end if 1271 | 1272 | } // end if 1273 | 1274 | } // end if 1275 | 1276 | if ( ( map[ i ] & 0x0f ) == 1 ) 1277 | { 1278 | // Point to next direction 1279 | map[ i ] &= 0xf0, map[ i ] |= 2; 1280 | 1281 | // Can we go right? 1282 | if ( x < ( w - 1 ) ) 1283 | { 1284 | n = y * sw + ( x + 1 ) * pw; 1285 | switch( bc ) 1286 | { case 24 : 1287 | ok = pImg[ n ] != r || pImg[ n + 1 ] != g || pImg[ n + 2 ] != b; 1288 | if ( ok ) ok = pImg[ n ] != br || pImg[ n + 1 ] != bg || pImg[ n + 2 ] != bb; 1289 | break; 1290 | case 32 : 1291 | ok = *(unsigned int*)&pImg[ n ] != x_col; 1292 | if ( ok ) ok = *(unsigned int*)&pImg[ n ] != x_bcol; 1293 | break; 1294 | } // end switch 1295 | 1296 | if ( ok ) 1297 | { x++; 1298 | i = y * w + x; 1299 | map[ i ] = 0x20; 1300 | ii = n; 1301 | } // end if 1302 | 1303 | } // end if 1304 | 1305 | } // end if 1306 | 1307 | if ( ( map[ i ] & 0x0f ) == 2 ) 1308 | { 1309 | // Point to next direction 1310 | map[ i ] &= 0xf0, map[ i ] |= 3; 1311 | 1312 | // Can we go down? 1313 | if ( y > 0 ) 1314 | { 1315 | n = ( y - 1 ) * sw + x * pw; 1316 | switch( bc ) 1317 | { case 24 : 1318 | ok = pImg[ n ] != r || pImg[ n + 1 ] != g || pImg[ n + 2 ] != b; 1319 | if ( ok ) ok = pImg[ n ] != br || pImg[ n + 1 ] != bg || pImg[ n + 2 ] != bb; 1320 | break; 1321 | case 32 : 1322 | ok = *(unsigned int*)&pImg[ n ] != x_col; 1323 | if ( ok ) ok = *(unsigned int*)&pImg[ n ] != x_bcol; 1324 | break; 1325 | } // end switch 1326 | 1327 | if ( ok ) 1328 | { y--; 1329 | i = y * w + x; 1330 | map[ i ] = 0x30; 1331 | ii = n; 1332 | } // end if 1333 | 1334 | } // end if 1335 | 1336 | } // end if 1337 | 1338 | if ( ( map[ i ] & 0x0f ) == 3 ) 1339 | { 1340 | // Point to next 1341 | map[ i ] &= 0xf0, map[ i ] |= 4; 1342 | 1343 | // Can we go left 1344 | if ( x > 0 ) 1345 | { 1346 | n = y * sw + ( x - 1 ) * pw; 1347 | switch( bc ) 1348 | { case 24 : 1349 | ok = pImg[ n ] != r || pImg[ n + 1 ] != g || pImg[ n + 2 ] != b; 1350 | if ( ok ) ok = pImg[ n ] != br || pImg[ n + 1 ] != bg || pImg[ n + 2 ] != bb; 1351 | break; 1352 | case 32 : 1353 | ok = *(unsigned int*)&pImg[ n ] != x_col; 1354 | if ( ok ) ok = *(unsigned int*)&pImg[ n ] != x_bcol; 1355 | break; 1356 | } // end switch 1357 | 1358 | if ( ok ) 1359 | { x--; 1360 | i = y * w + x; 1361 | map[ i ] = 0x40; 1362 | ii = n; 1363 | } // end if 1364 | 1365 | } // end if 1366 | 1367 | } // end if 1368 | 1369 | // Time to backup? 1370 | while ( ( map[ i ] & 0xf0 ) > 0 && ( map[ i ] & 0x0f ) > 3 ) 1371 | { 1372 | // Go back 1373 | if ( ( map[ i ] & 0xf0 ) == 0x10 ) y--; 1374 | else if ( ( map[ i ] & 0xf0 ) == 0x20 ) x--; 1375 | else if ( ( map[ i ] & 0xf0 ) == 0x30 ) y++; 1376 | else if ( ( map[ i ] & 0xf0 ) == 0x40 ) x++; 1377 | 1378 | // Set indexes 1379 | i = y * w + x; 1380 | ii = y * sw + x * pw; 1381 | 1382 | } // end while 1383 | 1384 | } // end if 1385 | 1386 | EZD_free( map ); 1387 | 1388 | return 1; 1389 | #endif 1390 | } 1391 | 1392 | // A small font map 1393 | static const unsigned char font_map_small [] = 1394 | { 1395 | // Default glyph 1396 | '.', 1, 6, 0x08, 1397 | 1398 | // Tab width 1399 | '\t', 8, 0, 1400 | 1401 | // Space 1402 | ' ', 3, 0, 1403 | 1404 | '!', 1, 6, 0xea, 1405 | '+', 3, 6, 0x0b, 0xa0, 0x00, 1406 | '-', 3, 6, 0x03, 0x80, 0x00, 1407 | '/', 3, 6, 0x25, 0x48, 0x00, 1408 | '*', 3, 6, 0xab, 0xaa, 0x00, 1409 | '@', 4, 6, 0x69, 0xbb, 0x87, 1410 | ':', 1, 6, 0x52, 1411 | '=', 3, 6, 0x1c, 0x70, 0x00, 1412 | '?', 4, 6, 0x69, 0x24, 0x04, 1413 | '%', 3, 6, 0x85, 0x28, 0x40, 1414 | '^', 3, 6, 0x54, 0x00, 0x00, 1415 | '#', 5, 6, 0x57, 0xd5, 0xf5, 0x00, 1416 | '$', 5, 6, 0x23, 0xe8, 0xe2, 0xf8, 1417 | '~', 4, 6, 0x05, 0xa0, 0x00, 1418 | 1419 | '0', 3, 6, 0x56, 0xd4, 0x31, 1420 | '1', 2, 6, 0xd5, 0x42, 1421 | '2', 4, 6, 0xe1, 0x68, 0xf0, 1422 | '3', 4, 6, 0xe1, 0x61, 0xe0, 1423 | '4', 4, 6, 0x89, 0xf1, 0x10, 1424 | '5', 4, 6, 0xf8, 0xe1, 0xe0, 1425 | '6', 4, 6, 0x78, 0xe9, 0x60, 1426 | '7', 4, 6, 0xf1, 0x24, 0x40, 1427 | '8', 4, 6, 0x69, 0x69, 0x60, 1428 | '9', 4, 6, 0x69, 0x71, 0x60, 1429 | 1430 | 'A', 4, 6, 0x69, 0xf9, 0x90, 1431 | 'B', 4, 6, 0xe9, 0xe9, 0xe0, 1432 | 'C', 4, 6, 0x78, 0x88, 0x70, 1433 | 'D', 4, 6, 0xe9, 0x99, 0xe0, 1434 | 'E', 4, 6, 0xf8, 0xe8, 0xf0, 1435 | 'F', 4, 6, 0xf8, 0xe8, 0x80, 1436 | 'G', 4, 6, 0x78, 0xb9, 0x70, 1437 | 'H', 4, 6, 0x99, 0xf9, 0x90, 1438 | 'I', 3, 6, 0xe9, 0x2e, 0x00, 1439 | 'J', 4, 6, 0xf2, 0x2a, 0x40, 1440 | 'K', 4, 6, 0x9a, 0xca, 0x90, 1441 | 'L', 3, 6, 0x92, 0x4e, 0x00, 1442 | 'M', 5, 6, 0x8e, 0xeb, 0x18, 0x80, 1443 | 'N', 4, 6, 0x9d, 0xb9, 0x90, 1444 | 'O', 4, 6, 0x69, 0x99, 0x60, 1445 | 'P', 4, 6, 0xe9, 0xe8, 0x80, 1446 | 'Q', 4, 6, 0x69, 0x9b, 0x70, 1447 | 'R', 4, 6, 0xe9, 0xea, 0x90, 1448 | 'S', 4, 6, 0x78, 0x61, 0xe0, 1449 | 'T', 3, 6, 0xe9, 0x24, 0x00, 1450 | 'U', 4, 6, 0x99, 0x99, 0x60, 1451 | 'V', 4, 6, 0x99, 0x96, 0x60, 1452 | 'W', 5, 6, 0x8c, 0x6b, 0x55, 0x00, 1453 | 'X', 4, 6, 0x99, 0x69, 0x90, 1454 | 'Y', 3, 6, 0xb5, 0x24, 0x00, 1455 | 'Z', 4, 6, 0xf2, 0x48, 0xf0, 1456 | 1457 | 'a', 4, 6, 0x69, 0xf9, 0x90, 1458 | 'b', 4, 6, 0xe9, 0xe9, 0xe0, 1459 | 'c', 4, 6, 0x78, 0x88, 0x70, 1460 | 'd', 4, 6, 0xe9, 0x99, 0xe0, 1461 | 'e', 4, 6, 0xf8, 0xe8, 0xf0, 1462 | 'f', 4, 6, 0xf8, 0xe8, 0x80, 1463 | 'g', 4, 6, 0x78, 0xb9, 0x70, 1464 | 'h', 4, 6, 0x99, 0xf9, 0x90, 1465 | 'i', 3, 6, 0xe9, 0x2e, 0x00, 1466 | 'j', 4, 6, 0xf2, 0x2a, 0x40, 1467 | 'k', 4, 6, 0x9a, 0xca, 0x90, 1468 | 'l', 3, 6, 0x92, 0x4e, 0x00, 1469 | 'm', 5, 6, 0x8e, 0xeb, 0x18, 0x80, 1470 | 'n', 4, 6, 0x9d, 0xb9, 0x90, 1471 | 'o', 4, 6, 0x69, 0x99, 0x60, 1472 | 'p', 4, 6, 0xe9, 0xe8, 0x80, 1473 | 'q', 4, 6, 0x69, 0x9b, 0x70, 1474 | 'r', 4, 6, 0xe9, 0xea, 0x90, 1475 | 's', 4, 6, 0x78, 0x61, 0xe0, 1476 | 't', 3, 6, 0xe9, 0x24, 0x00, 1477 | 'u', 4, 6, 0x99, 0x99, 0x60, 1478 | 'v', 4, 6, 0x99, 0x96, 0x60, 1479 | 'w', 5, 6, 0x8c, 0x6b, 0x55, 0x00, 1480 | 'x', 4, 6, 0x99, 0x69, 0x90, 1481 | 'y', 3, 6, 0xb5, 0x24, 0x00, 1482 | 'z', 4, 6, 0xf2, 0x48, 0xf0, 1483 | 1484 | 0, 1485 | }; 1486 | 1487 | // A medium font map 1488 | static const unsigned char font_map_medium [] = 1489 | { 1490 | // Default glyph 1491 | '.', 2, 10, 0x00, 0x3c, 0x00, 1492 | 1493 | // Tab width 1494 | '\t', 10, 0, 1495 | 1496 | // Space 1497 | ' ', 2, 0, 1498 | 1499 | '!', 1, 10, 0xf6, 0x00, 1500 | '(', 3, 10, 0x2a, 0x48, 0x88, 0x00, 1501 | ')', 3, 10, 0x88, 0x92, 0xa0, 0x00, 1502 | ',', 2, 10, 0x00, 0x16, 0x00, 1503 | '-', 3, 10, 0x00, 0x70, 0x00, 0x00, 1504 | '/', 3, 10, 0x25, 0x25, 0x20, 0x00, 1505 | '@', 6, 10, 0x7a, 0x19, 0x6b, 0x9a, 0x07, 0x80, 0x00, 0x00, 1506 | '$', 5, 10, 0x23, 0xab, 0x47, 0x16, 0xae, 0x20, 0x00, 1507 | '#', 6, 10, 0x49, 0x2f, 0xd2, 0xfd, 0x24, 0x80, 0x00, 0x00, 1508 | '%', 7, 10, 0x43, 0x49, 0x20, 0x82, 0x49, 0x61, 0x00, 0x00, 0x00, 1509 | ':', 2, 10, 0x3c, 0xf0, 0x00, 1510 | '^', 3, 10, 0x54, 0x00, 0x00, 0x00, 1511 | '~', 5, 10, 0x00, 0x11, 0x51, 0x00, 0x00, 0x00, 0x00, 1512 | 1513 | '0', 5, 10, 0x74, 0x73, 0x59, 0xc5, 0xc0, 0x00, 0x00, 1514 | '1', 3, 10, 0xc9, 0x24, 0xb8, 0x00, 1515 | '2', 5, 10, 0x74, 0x42, 0xe8, 0x43, 0xe0, 0x00, 0x00, 1516 | '3', 5, 10, 0x74, 0x42, 0xe0, 0xc5, 0xc0, 0x00, 0x00, 1517 | '4', 5, 10, 0x11, 0x95, 0x2f, 0x88, 0x40, 0x00, 0x00, 1518 | '5', 5, 10, 0xfc, 0x3c, 0x10, 0xc5, 0xc0, 0x00, 0x00, 1519 | '6', 5, 10, 0x74, 0x61, 0xe8, 0xc5, 0xc0, 0x00, 0x00, 1520 | '7', 5, 10, 0xfc, 0x44, 0x42, 0x10, 0x80, 0x00, 0x00, 1521 | '8', 5, 10, 0x74, 0x62, 0xe8, 0xc5, 0xc0, 0x00, 0x00, 1522 | '9', 5, 10, 0x74, 0x62, 0xf0, 0xc5, 0xc0, 0x00, 0x00, 1523 | 1524 | 'A', 6, 10, 0x31, 0x28, 0x7f, 0x86, 0x18, 0x40, 0x00, 0x00, 1525 | 'B', 6, 10, 0xfa, 0x18, 0x7e, 0x86, 0x1f, 0x80, 0x00, 0x00, 1526 | 'C', 6, 10, 0x7a, 0x18, 0x20, 0x82, 0x17, 0x80, 0x00, 0x00, 1527 | 'D', 6, 10, 0xfa, 0x18, 0x61, 0x86, 0x1f, 0x80, 0x00, 0x00, 1528 | 'E', 6, 10, 0xfe, 0x08, 0x3c, 0x82, 0x0f, 0xc0, 0x00, 0x00, 1529 | 'F', 6, 10, 0xfe, 0x08, 0x3c, 0x82, 0x08, 0x00, 0x00, 0x00, 1530 | 'G', 6, 10, 0x7a, 0x18, 0x27, 0x86, 0x17, 0xc0, 0x00, 0x00, 1531 | 'H', 6, 10, 0x86, 0x18, 0x7f, 0x86, 0x18, 0x40, 0x00, 0x00, 1532 | 'I', 3, 10, 0xe9, 0x24, 0xb8, 0x00, 1533 | 'J', 6, 10, 0xfc, 0x41, 0x04, 0x12, 0x46, 0x00, 0x00, 0x00, 1534 | 'K', 5, 10, 0x8c, 0xa9, 0x8a, 0x4a, 0x20, 0x00, 0x00, 1535 | 'L', 4, 10, 0x88, 0x88, 0x88, 0xf0, 0x00, 1536 | 'M', 6, 10, 0x87, 0x3b, 0x61, 0x86, 0x18, 0x40, 0x00, 0x00, 1537 | 'N', 5, 10, 0x8e, 0x6b, 0x38, 0xc6, 0x20, 0x00, 0x00, 1538 | 'O', 6, 10, 0x7a, 0x18, 0x61, 0x86, 0x17, 0x80, 0x00, 0x00, 1539 | 'P', 5, 10, 0xf4, 0x63, 0xe8, 0x42, 0x00, 0x00, 0x00, 1540 | 'Q', 6, 10, 0x7a, 0x18, 0x61, 0x86, 0x57, 0x81, 0x00, 0x00, 1541 | 'R', 5, 10, 0xf4, 0x63, 0xe8, 0xc6, 0x20, 0x00, 0x00, 1542 | 'S', 6, 10, 0x7a, 0x18, 0x1e, 0x06, 0x17, 0x80, 0x00, 0x00, 1543 | 'T', 3, 10, 0xe9, 0x24, 0x90, 0x00, 1544 | 'U', 6, 10, 0x86, 0x18, 0x61, 0x86, 0x17, 0x80, 0x00, 0x00, 1545 | 'V', 6, 10, 0x86, 0x18, 0x61, 0x85, 0x23, 0x00, 0x00, 0x00, 1546 | 'W', 7, 10, 0x83, 0x06, 0x4c, 0x99, 0x35, 0x51, 0x00, 0x00, 0x00, 1547 | 'X', 5, 10, 0x8c, 0x54, 0x45, 0x46, 0x20, 0x00, 0x00, 1548 | 'Y', 5, 10, 0x8c, 0x54, 0x42, 0x10, 0x80, 0x00, 0x00, 1549 | 'Z', 6, 10, 0xfc, 0x10, 0x84, 0x21, 0x0f, 0xc0, 0x00, 0x00, 1550 | 1551 | 'a', 4, 10, 0x00, 0x61, 0x79, 0x70, 0x00, 1552 | 'b', 4, 10, 0x88, 0xe9, 0x99, 0xe0, 0x00, 1553 | 'c', 4, 10, 0x00, 0x78, 0x88, 0x70, 0x00, 1554 | 'd', 4, 10, 0x11, 0x79, 0x99, 0x70, 0x00, 1555 | 'e', 4, 10, 0x00, 0x69, 0xf8, 0x60, 0x00, 1556 | 'f', 4, 10, 0x25, 0x4e, 0x44, 0x40, 0x00, 1557 | 'g', 4, 10, 0x00, 0x79, 0x99, 0x71, 0x60, 1558 | 'h', 4, 10, 0x88, 0xe9, 0x99, 0x90, 0x00, 1559 | 'i', 1, 10, 0xbe, 0x00, 1560 | 'j', 2, 10, 0x04, 0x55, 0x80, 1561 | 'k', 4, 10, 0x89, 0xac, 0xca, 0x90, 0x00, 1562 | 'l', 3, 10, 0xc9, 0x24, 0x98, 0x00, 1563 | 'm', 5, 10, 0x00, 0x15, 0x5a, 0xd6, 0x20, 0x00, 0x00, 1564 | 'n', 4, 10, 0x00, 0xe9, 0x99, 0x90, 0x00, 1565 | 'o', 4, 10, 0x00, 0x69, 0x99, 0x60, 0x00, 1566 | 'p', 4, 10, 0x00, 0xe9, 0x99, 0xe8, 0x80, 1567 | 'q', 4, 10, 0x00, 0x79, 0x97, 0x11, 0x10, 1568 | 'r', 3, 10, 0x02, 0xe9, 0x20, 0x00, 1569 | 's', 4, 10, 0x00, 0x78, 0x61, 0xe0, 0x00, 1570 | 't', 3, 10, 0x4b, 0xa4, 0x88, 0x00, 1571 | 'u', 4, 10, 0x00, 0x99, 0x99, 0x70, 0x00, 1572 | 'v', 4, 10, 0x00, 0x99, 0x99, 0x60, 0x00, 1573 | 'w', 5, 10, 0x00, 0x23, 0x1a, 0xd5, 0x40, 0x00, 0x00, 1574 | 'x', 5, 10, 0x00, 0x22, 0xa2, 0x2a, 0x20, 0x00, 0x00, 1575 | 'y', 4, 10, 0x00, 0x99, 0x99, 0x71, 0x60, 1576 | 'z', 4, 10, 0x00, 0xf1, 0x24, 0xf0, 0x00, 1577 | 1578 | 0, 1579 | 1580 | }; 1581 | 1582 | const char* ezd_next_glyph( const char* pGlyph ) 1583 | { 1584 | int sz; 1585 | 1586 | // Last glyph? 1587 | if ( !pGlyph || !*pGlyph ) 1588 | return 0; 1589 | 1590 | // Glyph size in bits 1591 | sz = pGlyph[ 1 ] * pGlyph[ 2 ]; 1592 | 1593 | // Return a pointer to the next glyph 1594 | return &pGlyph[ 3 + ( ( sz & 0x07 ) ? ( ( sz >> 3 ) + 1 ) : sz >> 3 ) ]; 1595 | } 1596 | 1597 | const char* ezd_find_glyph( HEZDFONT x_pFt, const char ch ) 1598 | { 1599 | #if !defined( EZD_STATIC_FONTS ) 1600 | 1601 | SFontData *f = (SFontData*)x_pFt; 1602 | 1603 | // Ensure valid font pointer 1604 | if ( !f ) 1605 | return 0; 1606 | 1607 | // Get a pointer to the glyph 1608 | return f->pIndex[ ch ]; 1609 | #else 1610 | 1611 | const char* pGlyph = (const char*)x_pFt; 1612 | 1613 | // Find the glyph 1614 | while ( pGlyph && *pGlyph ) 1615 | if ( ch == *pGlyph ) 1616 | return pGlyph; 1617 | else 1618 | pGlyph = ezd_next_glyph( pGlyph ); 1619 | 1620 | // First glyph is the default 1621 | return (const char*)x_pFt; 1622 | 1623 | #endif 1624 | } 1625 | 1626 | 1627 | HEZDFONT ezd_load_font( const void *x_pFt, int x_nFtSize, unsigned int x_uFlags ) 1628 | { 1629 | #if !defined( EZD_STATIC_FONTS ) 1630 | 1631 | int i, sz; 1632 | SFontData *p; 1633 | const unsigned char *pGlyph, *pFt = (const unsigned char*)x_pFt; 1634 | 1635 | // Font parameters 1636 | if ( !pFt ) 1637 | return _ERR( (HEZDFONT)0, "Invalid parameters" ); 1638 | 1639 | // Check for built in small font 1640 | if ( EZD_FONT_TYPE_SMALL == pFt ) 1641 | pFt = font_map_small, x_nFtSize = sizeof( font_map_small ); 1642 | 1643 | // Check for built in large font 1644 | else if ( EZD_FONT_TYPE_MEDIUM == pFt ) 1645 | pFt = font_map_medium, x_nFtSize = sizeof( font_map_medium ); 1646 | 1647 | // Check for built in large font 1648 | else if ( EZD_FONT_TYPE_LARGE == pFt ) 1649 | return 0; 1650 | 1651 | /// Null terminated font buffer? 1652 | if ( 0 >= x_nFtSize ) 1653 | { x_nFtSize = 0; 1654 | while ( pFt[ x_nFtSize ] ) 1655 | { sz = pFt[ x_nFtSize + 1 ] * pFt[ x_nFtSize + 2 ]; 1656 | x_nFtSize += 3 + ( ( sz & 0x07 ) ? ( ( sz >> 3 ) + 1 ) : sz >> 3 ); 1657 | } // end while 1658 | } // end if 1659 | 1660 | // Sanity check 1661 | if ( 0 >= x_nFtSize ) 1662 | return _ERR( (HEZDFONT)0, "Empty font table" ); 1663 | 1664 | // Allocate space for font buffer 1665 | p = (SFontData*)EZD_malloc( sizeof( SFontData ) + x_nFtSize ); 1666 | if ( !p ) 1667 | return 0; 1668 | 1669 | // Copy the font bitmaps 1670 | EZD_MEMCPY( p->pGlyph, pFt, x_nFtSize ); 1671 | 1672 | // Save font flags 1673 | p->uFlags = x_uFlags; 1674 | 1675 | // Use the first character as the default glyph 1676 | for( i = 0; i < 256; i++ ) 1677 | p->pIndex[ i ] = p->pGlyph; 1678 | 1679 | // Index the glyphs 1680 | pGlyph = p->pGlyph; 1681 | while ( pGlyph && *pGlyph ) 1682 | p->pIndex[ *pGlyph ] = pGlyph, 1683 | pGlyph = ezd_next_glyph( pGlyph ); 1684 | 1685 | // Return the font handle 1686 | return (HEZDFONT)p; 1687 | 1688 | #else 1689 | 1690 | // Convert type 1691 | const unsigned char *pFt = (const unsigned char*)x_pFt; 1692 | 1693 | // Font parameters 1694 | if ( !pFt ) 1695 | return _ERR( (HEZDFONT)0, "Invalid parameters" ); 1696 | 1697 | // Check for built in small font 1698 | if ( EZD_FONT_TYPE_SMALL == pFt ) 1699 | return (HEZDFONT)font_map_small; 1700 | 1701 | // Check for built in large font 1702 | else if ( EZD_FONT_TYPE_MEDIUM == pFt ) 1703 | return (HEZDFONT)font_map_medium; 1704 | 1705 | // Check for built in large font 1706 | else if ( EZD_FONT_TYPE_LARGE == pFt ) 1707 | return 0; 1708 | 1709 | // Just use the users raw font table pointer 1710 | else 1711 | return (HEZDFONT)x_pFt; 1712 | 1713 | #endif 1714 | } 1715 | 1716 | /// Releases the specified font 1717 | void ezd_destroy_font( HEZDFONT x_hFont ) 1718 | { 1719 | #if !defined( EZD_STATIC_FONTS ) 1720 | 1721 | if ( x_hFont ) 1722 | EZD_free( (SFontData*)x_hFont ); 1723 | 1724 | #endif 1725 | } 1726 | 1727 | int ezd_text_size( HEZDFONT x_hFont, const char *x_pText, int x_nTextLen, int *pw, int *ph ) 1728 | { 1729 | int i, w, h, lw = 0, lh = 0; 1730 | const unsigned char *pGlyph; 1731 | 1732 | // Sanity check 1733 | if ( !x_hFont || !pw || !ph ) 1734 | return _ERR( 0, "Invalid parameters" ); 1735 | 1736 | // Set all sizes to zero 1737 | *pw = *ph = 0; 1738 | 1739 | // For each character in the string 1740 | for ( i = 0; i < x_nTextLen || ( 0 > x_nTextLen && x_pText[ i ] ); i++ ) 1741 | { 1742 | // Get the specified glyph 1743 | pGlyph = ezd_find_glyph( x_hFont, x_pText[ i ] ); 1744 | 1745 | switch( x_pText[ i ] ) 1746 | { 1747 | // CR 1748 | case '\r' : 1749 | 1750 | // Reset width, and grab current height 1751 | w = 0; //h = lh; 1752 | i += ezd_text_size( x_hFont, &x_pText[ i + 1 ], x_nTextLen - i - 1, &w, &lh ); 1753 | 1754 | // Take the largest width / height 1755 | *pw = ( *pw > w ) ? *pw : w; 1756 | //lh = ( lh > h ) ? lh : h; 1757 | 1758 | break; 1759 | 1760 | // LF 1761 | case '\n' : 1762 | 1763 | // New line 1764 | w = 0; h = 0; 1765 | i += ezd_text_size( x_hFont, &x_pText[ i + 1 ], x_nTextLen - i - 1, &w, &h ); 1766 | 1767 | // Take the longest width 1768 | *pw = ( *pw > w ) ? *pw : w; 1769 | 1770 | // Add the height 1771 | *ph += h; 1772 | 1773 | break; 1774 | 1775 | // Regular character 1776 | default : 1777 | 1778 | // Accumulate width / height 1779 | lw += !lw ? pGlyph[ 1 ] : ( 2 + pGlyph[ 1 ] ), 1780 | lh = ( ( pGlyph[ 2 ] > lh ) ? pGlyph[ 2 ] : lh ); 1781 | 1782 | break; 1783 | 1784 | } // end switch 1785 | 1786 | } // end for 1787 | 1788 | // Take the longest width 1789 | *pw = ( *pw > lw ) ? *pw : lw; 1790 | 1791 | // Add our line height 1792 | *ph += lh; 1793 | 1794 | return i; 1795 | } 1796 | 1797 | static void ezd_draw_bmp_cb( unsigned char *pImg, int x, int y, int sw, int pw, 1798 | int inv, int bw, int bh, const unsigned char *pBmp, 1799 | int col, int ch, t_ezd_set_pixel pf, void *pUser ) 1800 | { 1801 | int w, h, lx = x; 1802 | unsigned char m = 0x80; 1803 | unsigned char r = col & 0xff; 1804 | unsigned char g = ( col >> 8 ) & 0xff; 1805 | unsigned char b = ( col >> 16 ) & 0xff; 1806 | static unsigned char xm[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; 1807 | 1808 | // Draw the glyph 1809 | for( h = 0; h < bh; h++ ) 1810 | { 1811 | // Draw horz line 1812 | for( w = 0; w < bw; w++ ) 1813 | { 1814 | // Next glyph byte? 1815 | if ( !m ) 1816 | m = 0x80, pBmp++; 1817 | 1818 | // Is this pixel on? 1819 | if ( *pBmp & m ) 1820 | if ( !pf( pUser, lx, y, col, ch ) ) 1821 | return; 1822 | 1823 | // Next bmp bit 1824 | m >>= 1; 1825 | 1826 | // Next x pixel 1827 | lx++; 1828 | 1829 | } // end for 1830 | 1831 | // Reset x 1832 | lx = x; 1833 | 1834 | // Reset y 1835 | y++; 1836 | 1837 | } // end for 1838 | 1839 | } 1840 | 1841 | static void ezd_draw_bmp_1( unsigned char *pImg, int x, int y, int sw, int pw, 1842 | int inv, int bw, int bh, const unsigned char *pBmp, int col ) 1843 | { 1844 | int w, h, lx = x; 1845 | unsigned char m = 0x80; 1846 | unsigned char r = col & 0xff; 1847 | unsigned char g = ( col >> 8 ) & 0xff; 1848 | unsigned char b = ( col >> 16 ) & 0xff; 1849 | static unsigned char xm[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; 1850 | 1851 | // Draw the glyph 1852 | for( h = 0; h < bh; h++ ) 1853 | { 1854 | // Draw horz line 1855 | for( w = 0; w < bw; w++ ) 1856 | { 1857 | // Next glyph byte? 1858 | if ( !m ) 1859 | m = 0x80, pBmp++; 1860 | 1861 | // Is this pixel on? 1862 | if ( *pBmp & m ) 1863 | if ( col ) 1864 | pImg[ y * sw + ( lx >> 3 ) ] |= xm[ lx & 7 ]; 1865 | else 1866 | pImg[ y * sw + ( lx >> 3 ) ] &= ~xm[ lx & 7 ]; 1867 | 1868 | // Next bmp bit 1869 | m >>= 1; 1870 | 1871 | // Next x pixel 1872 | lx++; 1873 | 1874 | } // end for 1875 | 1876 | // Reset x 1877 | lx = x; 1878 | 1879 | // Reset y 1880 | y++; 1881 | 1882 | } // end for 1883 | 1884 | } 1885 | 1886 | static void ezd_draw_bmp_24( unsigned char *pImg, int sw, int pw, int inv, 1887 | int bw, int bh, const unsigned char *pBmp, int col ) 1888 | { 1889 | int w, h; 1890 | unsigned char m = 0x80; 1891 | unsigned char r = col & 0xff; 1892 | unsigned char g = ( col >> 8 ) & 0xff; 1893 | unsigned char b = ( col >> 16 ) & 0xff; 1894 | 1895 | // Draw the glyph 1896 | for( h = 0; h < bh; h++ ) 1897 | { 1898 | // Draw horz line 1899 | for( w = 0; w < bw; w++ ) 1900 | { 1901 | // Next glyph byte? 1902 | if ( !m ) 1903 | m = 0x80, pBmp++; 1904 | 1905 | // Is this pixel on? 1906 | if ( *pBmp & m ) 1907 | pImg[ 0 ] = r, pImg[ 1 ] = g, pImg[ 2 ] = b; 1908 | 1909 | // Next bmp bit 1910 | m >>= 1; 1911 | 1912 | // Next pixel 1913 | pImg += pw; 1914 | 1915 | } // end for 1916 | 1917 | // Next image line 1918 | if ( 0 < inv ) 1919 | pImg += sw - ( bw * pw ); 1920 | else 1921 | pImg -= sw + ( bw * pw ); 1922 | 1923 | } // end for 1924 | 1925 | } 1926 | 1927 | static void ezd_draw_bmp_32( unsigned char *pImg, int sw, int pw, int inv, 1928 | int bw, int bh, const unsigned char *pBmp, int col ) 1929 | { 1930 | int w, h; 1931 | unsigned char m = 0x80; 1932 | 1933 | // Draw the glyph 1934 | for( h = 0; h < bh; h++ ) 1935 | { 1936 | // Draw horz line 1937 | for( w = 0; w < bw; w++ ) 1938 | { 1939 | // Next glyph byte? 1940 | if ( !m ) 1941 | m = 0x80, pBmp++; 1942 | 1943 | // Is this pixel on? 1944 | if ( *pBmp & m ) 1945 | *(unsigned int*)pImg = col; 1946 | 1947 | // Next bmp bit 1948 | m >>= 1; 1949 | 1950 | // Next pixel 1951 | pImg += pw; 1952 | 1953 | } // end for 1954 | 1955 | // Next image line 1956 | if ( 0 < inv ) 1957 | pImg += sw - ( bw * pw ); 1958 | else 1959 | pImg -= sw + ( bw * pw ); 1960 | 1961 | } // end for 1962 | 1963 | } 1964 | 1965 | int ezd_text( HEZDIMAGE x_hDib, HEZDFONT x_hFont, const char *x_pText, int x_nTextLen, int x, int y, int x_col ) 1966 | { 1967 | int w, h, sw, pw, inv, i, mh = 0, lx = x; 1968 | const unsigned char *pGlyph; 1969 | SImageData *p = (SImageData*)x_hDib; 1970 | 1971 | #if !defined( EZD_STATIC_FONTS ) 1972 | SFontData *f = (SFontData*)x_hFont; 1973 | if ( !f ) 1974 | return _ERR( 0, "Invalid parameters" ); 1975 | #endif 1976 | 1977 | // Sanity checks 1978 | if ( !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize 1979 | || ( !p->pImage && !p->pfSetPixel ) ) 1980 | return _ERR( 0, "Invalid parameters" ); 1981 | 1982 | // Calculate image metrics 1983 | w = EZD_ABS( p->bih.biWidth ); 1984 | h = EZD_ABS( p->bih.biHeight ); 1985 | 1986 | // Invert font? 1987 | inv = ( ( 0 < p->bih.biHeight ? 1 : 0 ) 1988 | #if !defined( EZD_STATIC_FONTS ) 1989 | ^ ( ( f->uFlags & EZD_FONT_FLAG_INVERT ) ? 1 : 0 ) 1990 | #endif 1991 | ) ? -1 : 1; 1992 | 1993 | // Pixel and scan width 1994 | pw = EZD_FITTO( p->bih.biBitCount, 8 ); 1995 | sw = EZD_SCANWIDTH( w, p->bih.biBitCount, 4 ); 1996 | 1997 | // For each character in the string 1998 | for ( i = 0; i < x_nTextLen || ( 0 > x_nTextLen && x_pText[ i ] ); i++ ) 1999 | { 2000 | // Get the specified glyph 2001 | pGlyph = ezd_find_glyph( x_hFont, x_pText[ i ] ); 2002 | 2003 | // CR, just go back to starting x pos 2004 | if ( '\r' == x_pText[ i ] ) 2005 | lx = x; 2006 | 2007 | // LF - Back to starting x and next line 2008 | else if ( '\n' == x_pText[ i ] ) 2009 | lx = x, y += inv * ( 1 + mh ), mh = 0; 2010 | 2011 | // Other characters 2012 | else 2013 | { 2014 | // Draw this glyph if it's completely on the screen 2015 | if ( pGlyph[ 1 ] && pGlyph[ 2 ] 2016 | && 0 <= lx && ( lx + pGlyph[ 1 ] ) < w 2017 | && 0 <= y && ( y + pGlyph[ 2 ] ) < h ) 2018 | { 2019 | // Check for user callback function 2020 | if ( p->pfSetPixel ) 2021 | ezd_draw_bmp_cb( p->pImage, lx, y, sw, pw, inv, 2022 | pGlyph[ 1 ], pGlyph[ 2 ], &pGlyph[ 3 ], 2023 | x_col, x_pText[ i ], p->pfSetPixel, p->pSetPixelUser ); 2024 | 2025 | else switch( p->bih.biBitCount ) 2026 | { 2027 | case 1 : 2028 | ezd_draw_bmp_1( p->pImage, lx, y, sw, pw, inv, 2029 | pGlyph[ 1 ], pGlyph[ 2 ], &pGlyph[ 3 ], 2030 | EZD_COMPARE_THRESHOLD( x_col, p->colThreshold ) ); 2031 | break; 2032 | 2033 | case 24 : 2034 | ezd_draw_bmp_24( &p->pImage[ y * sw + lx * pw ], sw, pw, inv, 2035 | pGlyph[ 1 ], pGlyph[ 2 ], &pGlyph[ 3 ], x_col ); 2036 | break; 2037 | 2038 | case 32 : 2039 | ezd_draw_bmp_32( &p->pImage[ y * sw + lx * pw ], sw, pw, inv, 2040 | pGlyph[ 1 ], pGlyph[ 2 ], &pGlyph[ 3 ], x_col ); 2041 | break; 2042 | } // end switch 2043 | 2044 | } // end if 2045 | 2046 | // Next character position 2047 | lx += 2 + pGlyph[ 1 ]; 2048 | 2049 | // Track max height 2050 | mh = ( pGlyph[ 2 ] > mh ) ? pGlyph[ 2 ] : mh; 2051 | 2052 | } // end else 2053 | 2054 | } // end for 2055 | 2056 | return 1; 2057 | } 2058 | 2059 | #define EZD_CNVTYPE( t, c ) case EZD_TYPE_##t : return oDst + ( (double)( ((c*)pData)[ i ] ) - oSrc ) * rDst / rSrc; 2060 | double ezd_scale_value( int i, int t, void *pData, double oSrc, double rSrc, double oDst, double rDst ) 2061 | { 2062 | switch( t ) 2063 | { 2064 | EZD_CNVTYPE( CHAR, char ); 2065 | EZD_CNVTYPE( UCHAR, unsigned char ); 2066 | EZD_CNVTYPE( SHORT, short ); 2067 | EZD_CNVTYPE( USHORT, unsigned short ); 2068 | EZD_CNVTYPE( INT, int ); 2069 | EZD_CNVTYPE( UINT, unsigned int ); 2070 | EZD_CNVTYPE( LONGLONG, long long ); 2071 | EZD_CNVTYPE( ULONGLONG, unsigned long long ); 2072 | EZD_CNVTYPE( FLOAT, float ); 2073 | EZD_CNVTYPE( DOUBLE, double ); 2074 | // EZD_CNVTYPE( LONGDOUBLE, long double ); 2075 | 2076 | default : 2077 | break; 2078 | 2079 | } // end switch 2080 | 2081 | return 0; 2082 | } 2083 | 2084 | double ezd_calc_range( int t, void *pData, int nData, double *pMin, double *pMax, double *pTotal ) 2085 | { 2086 | int i; 2087 | double v; 2088 | 2089 | // Sanity checks 2090 | if ( !pData || 0 >= nData ) 2091 | return 0; 2092 | 2093 | // Starting point 2094 | v = ezd_scale_value( 0, t, pData, 0, 1, 0, 1 ); 2095 | 2096 | if ( pMin ) 2097 | *pMin = v; 2098 | 2099 | if ( pMax ) 2100 | *pMax = v; 2101 | 2102 | if ( pTotal ) 2103 | *pTotal = 0; 2104 | 2105 | // Figure out the range 2106 | for ( i = 1; i < nData; i++ ) 2107 | { 2108 | // Get element value 2109 | v = ezd_scale_value( i, t, pData, 0, 1, 0, 1 ); 2110 | 2111 | // Track minimum 2112 | if ( pMin && v < *pMin ) 2113 | *pMin = v; 2114 | 2115 | // Track maximum 2116 | if ( pMax && v > *pMax ) 2117 | *pMax = v; 2118 | 2119 | // Accumulate total 2120 | if ( pTotal ) 2121 | *pTotal += v; 2122 | 2123 | } // end for 2124 | 2125 | return 1; 2126 | } 2127 | 2128 | -------------------------------------------------------------------------------- /assignments/ezdib/ezdib.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------ 2 | // Copyright (c) 1997 - 2012 3 | // Robert Umbehant 4 | // ezdib@wheresjames.com 5 | // http://www.wheresjames.com 6 | // 7 | // Redistribution and use in source and binary forms, with or 8 | // without modification, are permitted for commercial and 9 | // non-commercial purposes, provided that the following 10 | // conditions are met: 11 | // 12 | // * Redistributions of source code must retain the above copyright 13 | // notice, this list of conditions and the following disclaimer. 14 | // * The names of the developers or contributors may not be used to 15 | // endorse or promote products derived from this software without 16 | // specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 19 | // CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 20 | // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 | // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | //----------------------------------------------------------------*/ 32 | 33 | #pragma once 34 | 35 | #if defined( __cplusplus ) 36 | extern "C" 37 | { 38 | #endif 39 | 40 | /// Returns the absolute value of 'n' 41 | # define EZD_ABS( n ) ( ( 0 <= (n) ) ? (n) : -(n) ) 42 | 43 | /// Fits 'v' to unit size 'u' 44 | # define EZD_FITTO( v, u ) ( ( !(u) ) ? 0 : ( (v) / (u) ) + ( ( (v) % (u) ) ? 1 : 0 ) ) 45 | 46 | /// Aligns 'v' on block size 'a', 'a' must be a power of 2 47 | # define EZD_ALIGN( v, a ) ( ( (v) + ( (a) - 1 ) ) & ( ~( (a) - 1 ) ) ) 48 | 49 | /** Calculates scan width for a given 50 | \param [in] w - Line width in pixels 51 | \param [in] bpp - Bits per pixel 52 | \param [in] a - Alignment block size, must be power of 2 53 | */ 54 | # define EZD_SCANWIDTH( w, bpp, a ) ( EZD_ALIGN( EZD_FITTO( EZD_ABS( (w) ) * (bpp), 8 ), (a) ) ) 55 | 56 | /** Calculates image size for a given 57 | \param [in] w - Line width in pixels 58 | \param [in] h - Image height in pixels 59 | \param [in] bpp - Bits per pixel 60 | \param [in] a - Alignment block size, must be power of 2 61 | */ 62 | # define EZD_IMAGE_SIZE( w, h, bpp, a ) ( EZD_SCANWIDTH( (w), (bpp), (a) ) * EZD_ABS( (h) ) ) 63 | 64 | // Declare image handle 65 | struct _HEZDIMAGE; 66 | typedef struct _HEZDIMAGE *HEZDIMAGE; 67 | 68 | /// Bytes required for image header 69 | # define EZD_HEADER_SIZE 128 70 | 71 | /// Set this flag if you will supply your own image buffer using ezd_set_image_buffer() 72 | # define EZD_FLAG_USER_IMAGE_BUFFER 0x0001 73 | 74 | /// Set pixel function typedef. Supply your own set pixel 75 | /// function to support unbuffered io. 76 | /** 77 | \param [in] pUser - User data passed to ezd_set_pixel_callback() 78 | \param [in] x - X coord of pixel 79 | \param [in] y - Y coord of pixel 80 | \param [in] c - Pixel color 81 | \param [in] f - Flags 82 | 83 | \return Return non-zero to continue the current drawing operation, 84 | return zero to abort. 85 | */ 86 | typedef int (*t_ezd_set_pixel)( void *pUser, int x, int y, int c, int f ); 87 | 88 | /// Supply your own set pixel function to support unbuffered io. 89 | /** 90 | \param [in] x_pf - Pointer to user set pixel callback function. 91 | \param [in] x_pUser - Data passed to user callback function. 92 | 93 | If you don't need a buffer, you should pass the 94 | EZD_FLAG_USER_IMAGE_BUFFER flag to ezd_create() or ezd_initialize(). 95 | 96 | \return Non-zero if success, otherwise zero 97 | */ 98 | int ezd_set_pixel_callback( HEZDIMAGE x_hDib, t_ezd_set_pixel x_pf, void *x_pUser ); 99 | 100 | /// Returns the size buffer required for image headers 101 | /** 102 | If you use ezd_initialize(), you should call this function to get the 103 | number of bytes required for the buffer. 104 | 105 | If you absolutely must user a static buffer, use EZD_HEADER_SIZE, but 106 | be sure and pass EZD_HEADER_SIZE as the second parameter to 107 | ezd_initialize() to help detect space issues ;) 108 | 109 | */ 110 | int ezd_header_size(); 111 | 112 | /// Creates an empty image using a user supplied buffer 113 | /** 114 | \param [in] x_pBuffer - Pointer to user buffer 115 | \param [in] x_nBuffer - Size of buffer in x_pBuffer 116 | \param [in] x_lWidth - Image width 117 | \param [in] x_lHeight - Image height 118 | \param [in] x_lBpp - Image bits per pixel 119 | \param [in] x_uFlags - Image flags 120 | 121 | x_nBuffer 122 | 123 | This parameter can be zero if you don't want to verify the buffer you 124 | passed in is large enough. You should have allocated a buffer that is 125 | at least as large as the value returned by ezd_initialize(). 126 | 127 | x_lFlags 128 | 129 | EZD_FLAG_USER_IMAGE_BUFFER - Buffer does not include room for image data. 130 | User will provide buffer later by calling 131 | ezd_set_image_buffer(). 132 | 133 | \return Image handle or NULL if failure 134 | 135 | \see 136 | */ 137 | HEZDIMAGE ezd_initialize( void *x_pBuffer, int x_nBuffer, int x_lWidth, int x_lHeight, int x_lBpp, unsigned int x_uFlags ); 138 | 139 | /// Creates an empty image 140 | /** 141 | \param [in] x_lWidth - Image width 142 | \param [in] x_lHeight - Image height 143 | \param [in] x_lBpp - Image bits per pixel 144 | \param [in] x_uFlags - Image flags 145 | 146 | x_lFlags 147 | 148 | EZD_FLAG_USER_IMAGE_BUFFER - Do not allocate memory for image data, 149 | user will provide buffer by calling 150 | ezd_set_image_buffer(). 151 | 152 | \return Image handle or NULL if failure 153 | 154 | \see 155 | */ 156 | HEZDIMAGE ezd_create( int x_lWidth, int x_lHeight, int x_lBpp, unsigned int x_uFlags ); 157 | 158 | /// Releases the dib handle 159 | void ezd_destroy( HEZDIMAGE x_hDib ); 160 | 161 | /// Sets a pointer to the users image buffer 162 | /** 163 | \param [in] x_hDib - Handle to a dib 164 | \param [in] x_pImg - Pointer to use image buffer 165 | \param [in] x_nImg - Size of the buffer in x_pImg 166 | If it is not zero, it must match the size decided by 167 | ezd_crate() or the function will fail. 168 | 169 | Sets a pointer to the image data that is to be used. The caller is 170 | responsible for freeing the buffer. 171 | 172 | Use this function if you wish to substitute your own image buffer or 173 | used the EZD_FLAG_USER_IMAGE_BUFFER with ezd_create(). 174 | 175 | Calling this function with a NULL pointer will restore the buffer 176 | created by ezd_create(). If you passed the EZD_FLAG_USER_IMAGE_BUFFER 177 | to ezd_create(), then drawing functions will fail until you provide 178 | a buffer. 179 | 180 | */ 181 | int ezd_set_image_buffer( HEZDIMAGE x_hDib, void *x_pImg, int x_nImg ); 182 | 183 | /// Writes the DIB to a file 184 | /** 185 | \param [in] x_hDib - Handle to a dib 186 | \param [in] x_pFile - New image filename 187 | 188 | \return Non zero on success 189 | */ 190 | int ezd_save( HEZDIMAGE x_hDib, const char *x_pFile ); 191 | 192 | /// Sets the threshold color for 1 bit images 193 | /** 194 | \param [in] x_hDib - Handle to a dib 195 | \param [in] x_col - Threshold color 196 | 197 | Colors less than or equal to the threshold color are asigned 198 | a value of zero, while large colors are assigned a value of one. 199 | 200 | \return Non zero on success 201 | */ 202 | int ezd_set_color_threshold( HEZDIMAGE x_hDib, int x_col ); 203 | 204 | /// Sets the specified color in the color palette 205 | /** 206 | \param [in] x_hDib - Handle to a dib 207 | \param [in] x_idx - Color index to set 208 | \param [in] x_col - Threshold color 209 | 210 | Currently, this library only supports 1 bit images with 211 | color palettes. So x_idx must be zero or one. 212 | 213 | \return Non zero on success 214 | */ 215 | int ezd_set_palette_color( HEZDIMAGE x_hDib, int x_idx, int x_col ); 216 | 217 | /// Returns the specified color in the color palette 218 | /** 219 | \param [in] x_hDib - Handle to a dib 220 | \param [in] x_idx - Color index to set 221 | \param [in] x_col - Threshold color 222 | 223 | Currently, this library only supports 1 bit images with 224 | color palettes. So x_idx must be zero or one. 225 | 226 | \return Color of the specified palette index or zero if failure 227 | */ 228 | int ezd_get_palette_color( HEZDIMAGE x_hDib, int x_idx, int x_col ); 229 | 230 | /// Returns the number of color entries in the palette 231 | int ezd_get_palette_size( HEZDIMAGE x_hDib ); 232 | 233 | /// Returns a pointer to the palette 234 | int* ezd_get_palette( HEZDIMAGE x_hDib ); 235 | 236 | /// Fills the image with the specified color 237 | /** 238 | \param [in] x_hDib - Handle to a dib 239 | \param [in] x_col - Fill color 240 | 241 | \return Non zero on success 242 | */ 243 | int ezd_fill( HEZDIMAGE x_hDib, int x_col ); 244 | 245 | /// Returns the width of the specified image 246 | int ezd_get_width( HEZDIMAGE x_hDib ); 247 | 248 | /// Returns the height of the specified image 249 | int ezd_get_height( HEZDIMAGE x_hDib ); 250 | 251 | /// Returns the bits per pixel of the specified image 252 | int ezd_get_bpp( HEZDIMAGE x_hDib ); 253 | 254 | /// Returns the size in bytes of the image data 255 | int ezd_get_image_size( HEZDIMAGE x_hDib ); 256 | 257 | /// Returns a raw image 258 | void* ezd_get_image_ptr( HEZDIMAGE x_hDib ); 259 | 260 | /// Sets the specified pixel color 261 | /** 262 | \param [in] x_hDib - Handle to a dib 263 | \param [in] x - X coord 264 | \param [in] y - Y coord 265 | \param [in] x_col - Pixel color 266 | 267 | \return Non zero on success 268 | */ 269 | int ezd_set_pixel( HEZDIMAGE x_hDib, int x, int y, int x_col ); 270 | 271 | /// Returns the specified pixel color 272 | /** 273 | \param [in] x_hDib - Handle to a dib 274 | \param [in] x - X coord 275 | \param [in] y - Y coord 276 | 277 | \return The color of the specified pixel 278 | */ 279 | int ezd_get_pixel( HEZDIMAGE x_hDib, int x, int y ); 280 | 281 | 282 | /// Draws a line between the specified points 283 | /** 284 | \param [in] x_hDib - Handle to a dib 285 | \param [in] x1 - First X coord 286 | \param [in] y1 - First Y coord 287 | \param [in] x2 - Second X coord 288 | \param [in] y2 - Second Y coord 289 | \param [in] x_col - Line color 290 | 291 | \return Non zero on success 292 | */ 293 | int ezd_line( HEZDIMAGE x_hDib, int x1, int y1, int x2, int y2, int x_col ); 294 | 295 | /// Fills the specified rectangle 296 | /** 297 | \param [in] x_hDib - Handle to a dib 298 | \param [in] x1 - Top Left X coord 299 | \param [in] y1 - Top Left Y coord 300 | \param [in] x2 - Bottom Right X coord 301 | \param [in] y2 - Bottom Right Y coord 302 | \param [in] x_col - Fill color 303 | 304 | \return Non zero on success 305 | */ 306 | int ezd_fill_rect( HEZDIMAGE x_hDib, int x1, int y1, int x2, int y2, int x_col ); 307 | 308 | /// Outlines the specified rectangle 309 | /** 310 | \param [in] x_hDib - Handle to a dib 311 | \param [in] x1 - Top Left X coord 312 | \param [in] y1 - Top Left Y coord 313 | \param [in] x2 - Bottom Right X coord 314 | \param [in] y2 - Bottom Right Y coord 315 | \param [in] x_col - Line color 316 | 317 | \return Non zero on success 318 | */ 319 | int ezd_rect( HEZDIMAGE x_hDib, int x1, int y1, int x2, int y2, int x_col ); 320 | 321 | /// Draw circle outline 322 | /** 323 | \param [in] x_hDib - Handle to a dib 324 | \param [in] x - Center X coord 325 | \param [in] y - Center Y coord 326 | \param [in] r - Radius 327 | \param [in] dStart - Start angle 328 | \param [in] dEnd - End angle 329 | \param [in] x_col - Line color 330 | 331 | \return Non zero on success 332 | */ 333 | int ezd_arc( HEZDIMAGE x_hDib, int x, int y, int x_rad, double x_dStart, double x_dEnd, int x_col ); 334 | 335 | /// Draw circle outline 336 | /** 337 | \param [in] x_hDib - Handle to a dib 338 | \param [in] x - Center X coord 339 | \param [in] y - Center Y coord 340 | \param [in] r - Radius 341 | \param [in] x_col - Line color 342 | 343 | \return Non zero on success 344 | */ 345 | int ezd_circle( HEZDIMAGE x_hDib, int x, int y, int x_rad, int x_col ); 346 | 347 | /// Flood fill starting at the specified point 348 | /** 349 | \param [in] x_hDib - Handle to a dib 350 | \param [in] x - Start X coord 351 | \param [in] y - Start Y coord 352 | \param [in] x_bcol - Border color 353 | \param [in] x_col - Fill color 354 | */ 355 | int ezd_flood_fill( HEZDIMAGE x_hDib, int x, int y, int x_bcol, int x_col ); 356 | 357 | //-------------------------------------------------------------- 358 | // Font functions 359 | //-------------------------------------------------------------- 360 | 361 | // Declare handle 362 | struct _HEZDFONT; 363 | typedef struct _HEZDFONT *HEZDFONT; 364 | 365 | // Built in small font 366 | # define EZD_FONT_TYPE_SMALL ((unsigned char*)1) 367 | 368 | // Built in medium font 369 | # define EZD_FONT_TYPE_MEDIUM ((unsigned char*)2) 370 | 371 | // Built in large font 372 | # define EZD_FONT_TYPE_LARGE ((unsigned char*)3) 373 | 374 | /// Set this flag to invert the font 375 | # define EZD_FONT_FLAG_INVERT 0x01 376 | 377 | /// Loads a font map 378 | /** 379 | \param [in] x_pFt - Handle to a font map 380 | \param [in] x_pFtSize - Size of the specified font table 381 | 382 | This function basically just copies the specified 383 | font map and creates and index. 384 | 385 | \return Returns a handle to the loaded font 386 | */ 387 | HEZDFONT ezd_load_font( const void *x_pFt, int x_nFtSize, unsigned int x_uFlags ); 388 | 389 | /// Releases the specified font 390 | void ezd_destroy_font( HEZDFONT x_hFont ); 391 | 392 | /// Returns a pointer to the next glyph in a font map 393 | /** 394 | \return A pointer to the next glyph or zero if none 395 | */ 396 | const char* ezd_next_glyph( const char* pGlyph ); 397 | 398 | /// Searchs a font table for the specified glyph 399 | /** 400 | \param [in] x_pFt - Pointer to a null terminated font table 401 | \param [in] ch - Glyph to find 402 | 403 | \return A pointer to the glyph or zero if not found 404 | */ 405 | const char* ezd_find_glyph( HEZDFONT x_pFt, const char ch ); 406 | 407 | /// Draws the specified text string into the image 408 | /** 409 | \param [in] x_hDib - Image in which to draw the text 410 | \param [in] x_hFont - Font handle returned by ezd_load_font() 411 | \param [in] x_pText - Text string to draw 412 | \param [in] x_nTextLen - Length of the string in x_pText or zero 413 | for null terminated string. 414 | \param [in] x - The x coord to draw the text 415 | \param [in] y - The y coord to draw the text 416 | \param [in] x_col - Text color 417 | 418 | \return Returns non-zero on success 419 | */ 420 | int ezd_text( HEZDIMAGE x_hDib, HEZDFONT x_hFont, const char *x_pText, int x_nTextLen, int x, int y, int x_col ); 421 | 422 | /// Calculates the size of the specified text 423 | /** 424 | \param [in] x_hFont - Font handle returned by ezd_load_font() 425 | \param [in] x_pText - Text string to draw 426 | \param [in] x_nTextLen - Length of the string in x_pText or zero 427 | for null terminated string. 428 | \param [in] pw - Recieves the calculated width 429 | \param [in] ph - Receives the calculated height 430 | 431 | \return Returns number of characters in the text string that were considered 432 | */ 433 | int ezd_text_size( HEZDFONT x_hFont, const char *x_pText, int x_nTextLen, int *pw, int *ph ); 434 | 435 | //-------------------------------------------------------------- 436 | // Graph functions 437 | //-------------------------------------------------------------- 438 | 439 | // Element size 440 | # define EZD_TYPE_MASK_SIZE 0x00ff 441 | 442 | // Elements are signed values 443 | # define EZD_TYPE_MASK_SIGNED 0x0100 444 | 445 | // Array 446 | # define EZD_TYPE_MASK_ELEMENT 0x0200 447 | 448 | // Array 449 | # define EZD_TYPE_MASK_FLOATING 0x0400 450 | 451 | // Array 452 | # define EZD_TYPE_MASK_ARRAY 0x1000 453 | 454 | // Null terminated 455 | # define EZD_TYPE_MASK_NULLTERM 0x2000 456 | 457 | # define EZD_TYPE_NONE 0 458 | # define EZD_TYPE_SHORT ( EZD_TYPE_MASK_SIGNED | sizeof( short ) ) 459 | # define EZD_TYPE_USHORT ( sizeof( unsigned short ) ) 460 | # define EZD_TYPE_INT ( EZD_TYPE_MASK_SIGNED | sizeof( int ) ) 461 | # define EZD_TYPE_UINT ( sizeof( unsigned int ) ) 462 | # define EZD_TYPE_LONG ( EZD_TYPE_MASK_SIGNED | sizeof( long ) ) 463 | # define EZD_TYPE_ULONG ( sizeof( unsigned long ) ) 464 | # define EZD_TYPE_LONGLONG ( EZD_TYPE_MASK_SIGNED | sizeof( long long ) ) 465 | # define EZD_TYPE_ULONGLONG ( sizeof( unsigned long long ) ) 466 | 467 | # define EZD_TYPE_INT8 ( EZD_TYPE_MASK_SIGNED | 1 ) 468 | # define EZD_TYPE_UINT8 ( 1 ) 469 | # define EZD_TYPE_INT16 ( EZD_TYPE_MASK_SIGNED | 2 ) 470 | # define EZD_TYPE_UINT16 ( 2 ) 471 | # define EZD_TYPE_INT24 ( EZD_TYPE_MASK_SIGNED | 3 ) 472 | # define EZD_TYPE_UINT24 ( 3 ) 473 | # define EZD_TYPE_INT32 ( EZD_TYPE_MASK_SIGNED | 4 ) 474 | # define EZD_TYPE_UINT32 ( 4 ) 475 | # define EZD_TYPE_INT64 ( EZD_TYPE_MASK_SIGNED | 8 ) 476 | # define EZD_TYPE_UINT64 ( 8 ) 477 | 478 | # define EZD_TYPE_CHAR ( EZD_TYPE_MASK_ELEMENT | EZD_TYPE_MASK_SIGNED | sizeof( char ) ) 479 | # define EZD_TYPE_UCHAR ( EZD_TYPE_MASK_ELEMENT | sizeof( char ) ) 480 | # define EZD_TYPE_CHAR8 ( EZD_TYPE_MASK_ELEMENT | EZD_TYPE_MASK_SIGNED | 1 ) 481 | # define EZD_TYPE_UCHAR8 ( EZD_TYPE_MASK_ELEMENT | 1 ) 482 | # define EZD_TYPE_CHAR16 ( EZD_TYPE_MASK_ELEMENT | EZD_TYPE_MASK_SIGNED | 2 ) 483 | # define EZD_TYPE_UCHAR16 ( EZD_TYPE_MASK_ELEMENT | 2 ) 484 | # define EZD_TYPE_CHAR24 ( EZD_TYPE_MASK_ELEMENT | EZD_TYPE_MASK_SIGNED | 3 ) 485 | # define EZD_TYPE_UCHAR24 ( EZD_TYPE_MASK_ELEMENT | 3 ) 486 | # define EZD_TYPE_CHAR32 ( EZD_TYPE_MASK_ELEMENT | EZD_TYPE_MASK_SIGNED | 4 ) 487 | # define EZD_TYPE_UCHAR32 ( EZD_TYPE_MASK_ELEMENT | 4 ) 488 | 489 | # define EZD_TYPE_FLOAT ( EZD_TYPE_MASK_FLOATING | sizeof( float ) ) 490 | # define EZD_TYPE_FLOAT32 ( EZD_TYPE_MASK_FLOATING | 4 ) 491 | # define EZD_TYPE_FLOAT64 ( EZD_TYPE_MASK_FLOATING | 8 ) 492 | # define EZD_TYPE_DOUBLE ( EZD_TYPE_MASK_FLOATING | sizeof( double ) ) 493 | # define EZD_TYPE_LONGDOUBLE ( EZD_TYPE_MASK_FLOATING | sizeof( long double ) ) 494 | 495 | 496 | /// Returns the scaled value of the specified array element 497 | /** 498 | \param [in] i - Index of element in pData 499 | \param [in] t - Element type 500 | \param [in] pData - Pointer to an array of type t 501 | \param [in] oSrc - Source scale offset 502 | \param [in] rSrc - Source scale range 503 | \param [in] oDst - Destination scale offset 504 | \param [in] rDst - Destination scale range 505 | */ 506 | double ezd_scale_value( int i, int t, void *pData, double oSrc, double rSrc, double oDst, double rDst ); 507 | 508 | /// Calculates the range of the specified values 509 | /** 510 | \param [in] t - Element type 511 | \param [in] pData - Pointer to an array of type t 512 | \param [in] nData - Number of elements in pData 513 | \param [in] pMin - Pointer to a variable that receives the minimum 514 | \param [in] pMax - Pointer to a variable that receives the maximum 515 | */ 516 | double ezd_calc_range( int t, void *pData, int nData, double *pMin, double *pMax, double *pTotal ); 517 | 518 | #if defined( __cplusplus ) 519 | }; 520 | #endif 521 | 522 | -------------------------------------------------------------------------------- /assignments/ezdib/ezdib.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 9.00 3 | # Visual Studio 2005 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ezdib", "ezdib.vcproj", "{8576A305-13C8-47B2-97B7-69FF62B6D46B}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {8576A305-13C8-47B2-97B7-69FF62B6D46B}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {8576A305-13C8-47B2-97B7-69FF62B6D46B}.Debug|Win32.Build.0 = Debug|Win32 14 | {8576A305-13C8-47B2-97B7-69FF62B6D46B}.Release|Win32.ActiveCfg = Release|Win32 15 | {8576A305-13C8-47B2-97B7-69FF62B6D46B}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /assignments/ezdib/ezdib.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 25 | 28 | 31 | 34 | 37 | 40 | 52 | 55 | 58 | 61 | 68 | 71 | 74 | 77 | 80 | 83 | 86 | 89 | 92 | 93 | 101 | 104 | 107 | 110 | 113 | 116 | 125 | 128 | 131 | 134 | 143 | 146 | 149 | 152 | 155 | 158 | 161 | 164 | 167 | 168 | 169 | 170 | 171 | 172 | 177 | 180 | 181 | 184 | 185 | 186 | 191 | 194 | 195 | 196 | 201 | 202 | 203 | 204 | 205 | 206 | -------------------------------------------------------------------------------- /assignments/ezdib/main.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "ezdib.h" 8 | 9 | int bar_graph( HEZDIMAGE x_hDib, HEZDFONT x_hFont, int x1, int y1, int x2, int y2, 10 | int nDataType, void *pData, int nDataSize, int *pCols, int nCols ) 11 | { 12 | int i, c, w, h; 13 | int tyw = 0, bw = 0; 14 | double v, dMin, dMax, dRMin, dRMax; 15 | 16 | // Sanity checks 17 | if ( !pData || 0 >= nDataSize || !pCols || !nCols ) 18 | return 0; 19 | 20 | // Get the range of the data set 21 | ezd_calc_range( nDataType, pData, nDataSize, &dMin, &dMax, 0 ); 22 | 23 | // Add margin to range 24 | dRMin = dMin - ( dMax - dMin ) / 10; 25 | dRMax = dMax + ( dMax - dMin ) / 10; 26 | 27 | if ( x_hFont ) 28 | { 29 | char num[ 256 ] = { 0 }; 30 | 31 | // Calculate text width of smallest value 32 | sprintf( num, "%.2f", dMin ); 33 | ezd_text_size( x_hFont, num, -1, &tyw, &h ); 34 | ezd_text( x_hDib, x_hFont, num, -1, x1, y2 - ( h * 2 ), *pCols ); 35 | 36 | // Calculate text width of largest value 37 | sprintf( num, "%.2f", dMax ); 38 | ezd_text_size( x_hFont, num, -1, &w, &h ); 39 | ezd_text( x_hDib, x_hFont, num, -1, x1, y1 + h, *pCols ); 40 | if ( w > tyw ) 41 | tyw = w; 42 | 43 | // Text width margin 44 | tyw += 10; 45 | 46 | } // end if 47 | 48 | // Draw margins 49 | ezd_line( x_hDib, x1 + tyw - 2, y1, x1 + tyw - 2, y2, *pCols ); 50 | ezd_line( x_hDib, x1 + tyw - 2, y2, x2, y2, *pCols ); 51 | 52 | // Calculate bar width 53 | bw = ( x2 - x1 - tyw - nDataSize * 2 ) / nDataSize; 54 | 55 | // Draw the bars 56 | c = 0; 57 | for ( i = 0; i < nDataSize; i++ ) 58 | { 59 | if ( ++c >= nCols ) 60 | c = 1; 61 | 62 | // Get the value for this element 63 | v = ezd_scale_value( i, nDataType, pData, dRMin, dRMax - dRMin, 0, y2 - y1 - 2 ); 64 | 65 | // Fill in the bar 66 | ezd_fill_rect( x_hDib, x1 + tyw + i + ( ( bw + 1 ) * i ), y2 - (int)v - 2, 67 | x1 + tyw + i + ( ( bw + 1 ) * i ) + bw, y2 - 2, pCols[ c ] ); 68 | 69 | // Outline the bar 70 | ezd_rect( x_hDib, x1 + tyw + i + ( ( bw + 1 ) * i ), y2 - (int)v - 2, 71 | x1 + tyw + i + ( ( bw + 1 ) * i ) + bw, y2 - 2, *pCols ); 72 | } // end for 73 | 74 | return 1; 75 | } 76 | 77 | #define PI ( (double)3.141592654 ) 78 | #define PI2 ( (double)2 * PI ) 79 | 80 | int pie_graph( HEZDIMAGE x_hDib, int x, int y, int rad, 81 | int nDataType, void *pData, int nDataSize, int *pCols, int nCols ) 82 | { 83 | int i, c; 84 | double v, pos, dMin, dMax, dTotal; 85 | 86 | // Sanity checks 87 | if ( !pData || 0 >= nDataSize || !pCols || !nCols ) 88 | return 0; 89 | 90 | // Draw chart outline 91 | ezd_circle( x_hDib, x, y, rad, *pCols ); 92 | 93 | // Get the range of the data set 94 | ezd_calc_range( nDataType, pData, nDataSize, &dMin, &dMax, &dTotal ); 95 | 96 | // Draw the pie slices 97 | pos = 0; c = 0; 98 | ezd_line( x_hDib, x, y, x + rad, y, *pCols ); 99 | for ( i = 0; i < nDataSize; i++ ) 100 | { 101 | if ( ++c >= nCols ) 102 | c = 1; 103 | 104 | // Get the value for this element 105 | v = ezd_scale_value( i, nDataType, pData, 0, dTotal, 0, PI2 ); 106 | 107 | ezd_line( x_hDib, x, y, 108 | x + (int)( (double)rad * cos( pos + v ) ), 109 | y + (int)( (double)rad * sin( pos + v ) ), 110 | *pCols ); 111 | 112 | ezd_flood_fill( x_hDib, x + (int)( (double)rad / (double)2 * cos( pos + v / 2 ) ), 113 | y + (int)( (double)rad / (double)2 * sin( pos + v / 2 ) ), 114 | *pCols, pCols[ c ] ); 115 | 116 | pos += v; 117 | 118 | } // end for 119 | 120 | return 1; 121 | } 122 | 123 | typedef struct _SAsciiData 124 | { 125 | int sw; 126 | unsigned char *buf; 127 | } SAsciiData; 128 | 129 | int ascii_writer( void *pUser, int x, int y, int c, int f ) 130 | { 131 | SAsciiData *p = (SAsciiData*)pUser; 132 | unsigned char ch = (unsigned char)( f & 0xff ); 133 | 134 | if ( !p ) 135 | return 0; 136 | 137 | if ( ( '0' <= ch && '9' >= ch ) 138 | || ( 'A' <= ch && 'Z' >= ch ) 139 | || ( 'a' <= ch && 'z' >= ch ) ) 140 | 141 | // Write the character 142 | p->buf[ y * p->sw + x ] = (unsigned char)f; 143 | 144 | else 145 | 146 | // Write the color 147 | p->buf[ y * p->sw + x ] = (unsigned char)c; 148 | 149 | return 1; 150 | } 151 | 152 | typedef struct _SDotMatrixData 153 | { 154 | int w; 155 | int h; 156 | HEZDIMAGE pDib; 157 | } SDotMatrixData; 158 | 159 | int dotmatrix_writer( void *pUser, int x, int y, int c, int f ) 160 | { 161 | int cc, r, dw = 3; 162 | HEZDIMAGE hDib = (HEZDIMAGE)pUser; 163 | 164 | if ( !hDib ) 165 | return 0; 166 | 167 | cc = c & 0xff; 168 | for ( r = 0; r < dw; r++ ) 169 | { ezd_circle( hDib, x * dw * 2 , y * dw * 2, r, cc ); 170 | if ( r ) cc >>= 1; 171 | } // end for 172 | 173 | cc = ( c >> 8 ) & 0xff; 174 | for ( r = 0; r < dw; r++ ) 175 | { ezd_circle( hDib, x * dw * 2 + dw, y * dw * 2, r, cc << 8 ); 176 | if ( r ) cc >>= 1; 177 | } // end for 178 | 179 | cc = c & 0xff; 180 | for ( r = 0; r < dw; r++ ) 181 | { ezd_circle( hDib, x * dw * 2 + dw, y * dw * 2 + dw, r, cc ); 182 | if ( r ) cc >>= 1; 183 | } // end for 184 | 185 | cc = ( c >> 16 ) & 0xff; 186 | for ( r = 0; r < dw; r++ ) 187 | { ezd_circle( hDib, x * dw * 2, y * dw * 2 + dw, r, cc << 16 ); 188 | if ( r ) cc >>= 1; 189 | } // end for 190 | 191 | return 1; 192 | } 193 | 194 | int main( int argc, char* argv[] ) 195 | { 196 | int b, x, y; 197 | HEZDIMAGE hDib; 198 | HEZDFONT hFont; 199 | 200 | // Create output file name 201 | 202 | // Create image 203 | hDib = ezd_create( 640, -480, 32, 0 ); 204 | if ( !hDib ) 205 | return 1 ; 206 | 207 | // Fill in the background 208 | ezd_fill( hDib, 0x404040 ); 209 | 210 | // Test fonts 211 | hFont = ezd_load_font( EZD_FONT_TYPE_MEDIUM, 0, 0 ); 212 | if ( hFont ) 213 | ezd_text( hDib, hFont, "--- EZDIB Test ---", -1, 10, 10, 0xffffff ); 214 | 215 | // Draw random lines 216 | for ( x = 20; x < 300; x += 10 ) 217 | ezd_line( hDib, x, ( x & 1 ) ? 50 : 100, x + 10, !( x & 1 ) ? 50 : 100, 0x00ff00 ), 218 | ezd_line( hDib, x + 10, ( x & 1 ) ? 50 : 100, x, !( x & 1 ) ? 50 : 100, 0x0000ff ); 219 | 220 | // Random red box 221 | ezd_fill_rect( hDib, 200, 150, 400, 250, 0x900000 ); 222 | 223 | // Random yellow box 224 | ezd_fill_rect( hDib, 300, 200, 350, 280, 0xffff00 ); 225 | 226 | // Dark outline for yellow box 227 | ezd_rect( hDib, 300, 200, 350, 280, 0x000000 ); 228 | 229 | // Draw random dots 230 | for ( y = 150; y < 250; y += 4 ) 231 | for ( x = 50; x < 150; x += 4 ) 232 | ezd_set_pixel( hDib, x, y, 0xffffff ); 233 | 234 | // Circles 235 | for ( x = 0; x < 40; x++ ) 236 | ezd_circle( hDib, 400, 60, x, x * 5 ); 237 | 238 | // Draw graphs 239 | { 240 | // Graph data 241 | int data[] = { 11, 54, 23, 87, 34, 54, 75, 44, 66 }; 242 | 243 | // Graph colors 244 | int cols[] = { 0xffffff, 0x400000, 0x006000, 0x000080 }; 245 | 246 | // Draw bar graph 247 | ezd_rect( hDib, 35, 295, 605, 445, cols[ 0 ] ); 248 | bar_graph( hDib, hFont, 40, 300, 600, 440, EZD_TYPE_INT, 249 | data, sizeof( data ) / sizeof( data[ 0 ] ), 250 | cols, sizeof( cols ) / sizeof( cols[ 0 ] ) ); 251 | 252 | // Draw pie graph 253 | ezd_circle( hDib, 525, 150, 84, cols[ 0 ] ); 254 | pie_graph( hDib, 525, 150, 80, EZD_TYPE_INT, 255 | data, sizeof( data ) / sizeof( data[ 0 ] ), 256 | cols, sizeof( cols ) / sizeof( cols[ 0 ] ) ); 257 | 258 | } 259 | 260 | // Save the test image 261 | ezd_save( hDib, "output.bmp"); 262 | 263 | /// Releases the specified font 264 | if ( hFont ) 265 | ezd_destroy_font( hFont ); 266 | 267 | // Free resources 268 | if ( hDib ) 269 | ezd_destroy( hDib ); 270 | 271 | return 0; 272 | } 273 | -------------------------------------------------------------------------------- /assignments/gram.txt: -------------------------------------------------------------------------------- 1 | S ::= E 2 | E ::= "(" E "/\" E ")" 3 | E ::= "(" E "\/" E ")" 4 | E ::= "!(" E ")" 5 | E ::= "p" 6 | E ::= "q" 7 | E ::= "True" 8 | E ::= "False" -------------------------------------------------------------------------------- /assignments/homework1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/assignments/homework1.pdf -------------------------------------------------------------------------------- /assignments/homework2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/assignments/homework2.pdf -------------------------------------------------------------------------------- /assignments/homework3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/assignments/homework3.pdf -------------------------------------------------------------------------------- /assignments/homework4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/assignments/homework4.pdf -------------------------------------------------------------------------------- /assignments/nqueen-sat.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | min(int a, int b) 5 | { 6 | if (a > b) 7 | return b ; 8 | return a ; 9 | } 10 | 11 | int 12 | main () 13 | { 14 | FILE * fp = fopen("formula", "w") ; 15 | 16 | int i, j, k ; 17 | 18 | for (i = 1 ; i <= 8 ; i++) 19 | for (j = 1 ; j <= 8 ; j++) 20 | fprintf(fp,"(declare-const p%d%d Bool)\n", i, j) ; 21 | 22 | // Q1 23 | fprintf(fp,"; Q1\n") ; 24 | fprintf(fp,"(assert (and ") ; 25 | for (i = 1 ; i <= 8 ; i++) { 26 | fprintf(fp,"(or ") ; 27 | for (j = 1 ; j <= 8 ; j++) 28 | fprintf(fp,"p%d%d ", i, j) ; 29 | fprintf(fp,")") ; 30 | } 31 | fprintf(fp,"))\n") ; 32 | 33 | fprintf(fp,"; Q2\n") ; 34 | fprintf(fp,"(assert ") ; 35 | fprintf(fp,"(and ") ; 36 | for (i = 1 ; i <= 8 ; i++) { 37 | fprintf(fp,"(and ") ; 38 | for (j = 1 ; j <= 7 ; j++) { 39 | fprintf(fp,"(and ") ; 40 | for (k = j + 1 ; k <= 8 ; k++) { 41 | fprintf(fp,"(not (and p%d%d p%d%d))", i, j, i, k) ; 42 | } 43 | fprintf(fp,")") ; 44 | } 45 | fprintf(fp,") ") ; 46 | } 47 | fprintf(fp,"))\n") ; 48 | 49 | // Q3 50 | fprintf(fp,"; Q3\n") ; 51 | fprintf(fp,"(assert (and ") ; 52 | for (j = 1 ; j <= 8 ; j++) { 53 | fprintf(fp,"(or ") ; 54 | for (i = 1 ; i <= 8 ; i++) 55 | fprintf(fp,"p%d%d ", i, j) ; 56 | fprintf(fp,")") ; 57 | } 58 | fprintf(fp,"))\n") ; 59 | 60 | // Q4 61 | fprintf(fp,"; Q4\n") ; 62 | fprintf(fp,"(assert ") ; 63 | fprintf(fp,"(and ") ; 64 | for (i = 1 ; i <= 8 ; i++) { 65 | fprintf(fp,"(and ") ; 66 | for (j = 1 ; j <= 7 ; j++) { 67 | fprintf(fp,"(and ") ; 68 | for (k = j + 1 ; k <= 8 ; k++) { 69 | fprintf(fp,"(not (and p%d%d p%d%d))", j, i, k, i) ; 70 | } 71 | fprintf(fp,")") ; 72 | } 73 | fprintf(fp,") ") ; 74 | } 75 | fprintf(fp,"))\n") ; 76 | 77 | // Q5 78 | fprintf(fp,"; Q5\n") ; 79 | fprintf(fp,"(assert ") ; 80 | fprintf(fp,"(and ") ; 81 | for (i = 2 ; i <= 8 ; i++) { 82 | fprintf(fp,"(and ") ; 83 | for (j = 1 ; j <= 7 ; j++) { 84 | fprintf(fp,"(and ") ; 85 | for (k = 1 ; k <= min(i - 1, 8 - j) ; k++) { 86 | fprintf(fp,"(not (and p%d%d p%d%d))", i, j, i - k, k + j) ; 87 | } 88 | fprintf(fp,")") ; 89 | } 90 | fprintf(fp,") ") ; 91 | } 92 | fprintf(fp,"))\n") ; 93 | 94 | // Q6 95 | fprintf(fp,"; Q6\n") ; 96 | fprintf(fp,"(assert ") ; 97 | fprintf(fp,"(and ") ; 98 | for (i = 1 ; i <= 7 ; i++) { 99 | fprintf(fp,"(and ") ; 100 | for (j = 1 ; j <= 7 ; j++) { 101 | fprintf(fp,"(and ") ; 102 | for (k = 1 ; k <= min(8 - i, 8 - j) ; k++) { 103 | fprintf(fp,"(not (and p%d%d p%d%d))", i, j, i + k, j + k) ; 104 | } 105 | fprintf(fp,")") ; 106 | } 107 | fprintf(fp,") ") ; 108 | } 109 | fprintf(fp,"))\n") ; 110 | 111 | fprintf(fp,"(check-sat)\n(get-model)\n") ; 112 | 113 | fclose(fp) ; 114 | 115 | FILE * fin = popen("z3 formula", "r") ; 116 | char buf[128] ; 117 | fscanf(fin, "%s %s", buf, buf) ; 118 | while (!feof(fin)) { 119 | fscanf(fin, "%s", buf) ; //printf("%s ", buf) ; 120 | fscanf(fin, "%s", buf) ; printf("%s ", buf) ; 121 | fscanf(fin, "%s", buf) ; //printf("%s ", buf) ; 122 | fscanf(fin, "%s", buf) ; //printf("%s ", buf) ; 123 | fscanf(fin, "%s", buf) ; printf("%s\n", buf) ; 124 | } 125 | pclose(fin) ; 126 | 127 | } 128 | 129 | -------------------------------------------------------------------------------- /assignments/peer+evaluation.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/assignments/peer+evaluation.xlsx -------------------------------------------------------------------------------- /assignments/reading+group.md: -------------------------------------------------------------------------------- 1 | ### Week 13 ### 2 | * solve the following exercise problems: 3 | - Ch. 9.3: 6, 10, 29 4 | - Ch. 9.5: 2, 3, 14, 33 5 | - Ch. 9.6: 3, 7, 22, 32 6 | 7 | ### Week 12 ### 8 | * solve the following exercise problems: 9 | - Ch. 7.2: 28, 30, 36 10 | - Ch. 7.3: 9, 17, 18 11 | - Ch. 9.1: 6, 22, 53, 57 12 | 13 | ### Week 11 ### 14 | * solve the following exercise problems: 15 | - Ch. 6.3: 22, 30 16 | - Ch. 6.4: 12, 37 17 | - Ch. 6.5: 16 18 | - Ch. 7.1: 25, 42 19 | - Ch. 7.2: 11, 16 20 | 21 | ### Week 10 ### 22 | * write a C program that generates the member strings (without receiving the grammar) specifically for the first recursive language problem of Homework 3. 23 | * solve the following exercise problems: 24 | - Ch. 6.1: 41, 42, 43 25 | - Ch. 6.2: 11, 21 26 | 27 | ### Week 8 ### 28 | * read Chapters 5.3 and 5.4 29 | * solve the following exercise problems: 30 | - Ch. 5.3: 20, 25, 42, 46 31 | - Ch. 5.4: 8, 10, 24 32 | 33 | ### Week 7 ### 34 | * read Chatpers 3.1 and 3.2, and 5.1 and 5.2 35 | * solve the following exercise problems: 36 | - Ch. 3.2: 9, 17 37 | - Ch. 5.1: 19, 20, 41 38 | - Ch. 5.2: 3, 12 39 | 40 | ### Week 6 ### 41 | * read Chapters 2.1--2.5 42 | * solve the following exercise problems: 43 | - Ch. 2.1: 12 44 | - Ch. 2.2: 21 45 | - Ch. 2.3: 33, 42 46 | - Ch. 2.5: 3, 35 47 | 48 | ### Week 4 ### 49 | * write a C program that uses Z3 to find a solution of a given Sudozu puzzle 50 | * describe the design and the implementation of your Sudoku solving program in the Google Doc report (by 11:59 PM, Sep 28) 51 | 52 | ### Week 3 ### 53 | * read Chapteres 1.6-1.8 54 | * solve the following exercise problems: 55 | - Ch. 1.6: 12, 29 56 | - Ch. 1.7: 9, 17, 28 57 | - Ch. 1.8: 19, 36 58 | 59 | 60 | ### Week 2 ### 61 | * read Chapters 1.4-1.5 62 | * solve the following exercise problems: 63 | - Ch. 1.4: Exercises 14, 20, 35, 53 64 | - Ch. 1.5: Exercises 4, 26, 42 65 | 66 | 67 | ### Week 1 ### 68 | * read Chapters 1.1-1.3.4 (pp. 1—32) 69 | * solve the following exercise problems: 70 | - Ch.1.1: Exercises 18, 29 and 40 71 | - Ch.1.2: Exercise 5 72 | - Ch.1.3: Exercises 9 and 11 73 | -------------------------------------------------------------------------------- /assignments/report.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/assignments/report.docx -------------------------------------------------------------------------------- /notes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/.gitkeep -------------------------------------------------------------------------------- /notes/algorithm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/algorithm.pdf -------------------------------------------------------------------------------- /notes/cardinality.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/cardinality.pdf -------------------------------------------------------------------------------- /notes/counting.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/counting.pdf -------------------------------------------------------------------------------- /notes/course+overview.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/course+overview.pdf -------------------------------------------------------------------------------- /notes/graph.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/graph.pdf -------------------------------------------------------------------------------- /notes/halting+problem.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/halting+problem.pdf -------------------------------------------------------------------------------- /notes/induction.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/induction.pdf -------------------------------------------------------------------------------- /notes/inference.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/inference.pdf -------------------------------------------------------------------------------- /notes/predicate+logic.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/predicate+logic.pdf -------------------------------------------------------------------------------- /notes/probability.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/probability.pdf -------------------------------------------------------------------------------- /notes/proof.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/proof.pdf -------------------------------------------------------------------------------- /notes/prop+logic+solver.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/prop+logic+solver.pdf -------------------------------------------------------------------------------- /notes/propositional+logic.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/propositional+logic.pdf -------------------------------------------------------------------------------- /notes/recursion.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/recursion.pdf -------------------------------------------------------------------------------- /notes/relation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/relation.pdf -------------------------------------------------------------------------------- /notes/sequence.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/sequence.pdf -------------------------------------------------------------------------------- /notes/set+function.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/set+function.pdf -------------------------------------------------------------------------------- /notes/test1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/test1.pdf -------------------------------------------------------------------------------- /notes/test2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/test2.pdf -------------------------------------------------------------------------------- /notes/test3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/test3.pdf -------------------------------------------------------------------------------- /notes/test4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/notes/test4.pdf -------------------------------------------------------------------------------- /resource/17-final.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/resource/17-final.pdf -------------------------------------------------------------------------------- /resource/17-midterm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/resource/17-midterm.pdf -------------------------------------------------------------------------------- /resource/18-final.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/resource/18-final.pdf -------------------------------------------------------------------------------- /resource/18-midterm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/resource/18-midterm.pdf -------------------------------------------------------------------------------- /resource/18-quiz-01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/resource/18-quiz-01.pdf -------------------------------------------------------------------------------- /resource/18-quiz-02.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/resource/18-quiz-02.pdf -------------------------------------------------------------------------------- /resource/19-final.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/resource/19-final.pdf -------------------------------------------------------------------------------- /resource/19-midterm-01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/resource/19-midterm-01.pdf -------------------------------------------------------------------------------- /resource/19-midterm-02.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/resource/19-midterm-02.pdf -------------------------------------------------------------------------------- /resource/20-final.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/resource/20-final.pdf -------------------------------------------------------------------------------- /resource/20-midterm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongshin/DiscreteMath/f680d2a64f720bd62449052b2516c3cba2946a60/resource/20-midterm.pdf --------------------------------------------------------------------------------