├── LICENSE
├── README.md
├── images
├── Pixellib_anti_aliasing.png
├── Pixellib_geometry.png
├── Pixellib_image_drawing.png
├── Pixellib_image_transform.png
├── Pixellib_image_warp.png
└── Pixellib_quality.png
├── pixellib
├── ibitmap.c
├── ibitmap.h
├── iblit386.c
├── iblit386.h
├── ibmbits.c
├── ibmbits.h
├── ibmcols.c
├── ibmcols.h
├── ibmdata.c
├── ibmdata.h
├── ibmfont.c
├── ibmfont.h
├── ibmsse2.c
├── ibmsse2.h
├── ibmwink.c
├── ibmwink.h
├── ikitwin.c
├── ikitwin.h
├── ipicture.c
├── ipicture.h
├── mswindx.c
├── mswindx.h
├── npixel.c
└── npixel.h
└── wrap
├── PixelBitmap.cpp
├── PixelBitmap.h
├── PixelWin32.cpp
└── PixelWin32.h
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
341 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Description
2 | -----------
3 | - High Quality Anti-Alising Vector/Raster Graphics
4 | - Multi-Pixel-Format: RGB, BGR, ARGB, ABGR, RGBA, BGRA
5 | 8 / 15 / 16 / 24 / 32 depth
6 | - Light weight 100% C implementation
7 | - SSE2/MMX Graphics Optimized
8 |
9 | Samples
10 | -------
11 |
12 | Samples with executable can be download from [here](https://pixellib.googlecode.com/files/pixellib-samples-1.2.67.7z "here") .
13 |
14 | **Image Transform**
15 |
16 | 
17 |
18 | **Anti Aliasing**
19 |
20 | 
21 |
22 | **Image Drawing**
23 |
24 | 
25 |
26 | **Geometry Render**
27 |
28 | 
29 |
30 | **Image Warp**
31 |
32 | 
33 |
34 | **High Quality Render**
35 |
36 | 
37 |
38 |
39 | Donation
40 | --------
41 | 
42 |
43 | Call for donation to help improve performance and quality, scan QR code of alipay to donate.
44 |
45 |
46 |
--------------------------------------------------------------------------------
/images/Pixellib_anti_aliasing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/images/Pixellib_anti_aliasing.png
--------------------------------------------------------------------------------
/images/Pixellib_geometry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/images/Pixellib_geometry.png
--------------------------------------------------------------------------------
/images/Pixellib_image_drawing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/images/Pixellib_image_drawing.png
--------------------------------------------------------------------------------
/images/Pixellib_image_transform.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/images/Pixellib_image_transform.png
--------------------------------------------------------------------------------
/images/Pixellib_image_warp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/images/Pixellib_image_warp.png
--------------------------------------------------------------------------------
/images/Pixellib_quality.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/images/Pixellib_quality.png
--------------------------------------------------------------------------------
/pixellib/ibitmap.c:
--------------------------------------------------------------------------------
1 | /**********************************************************************
2 | *
3 | * ibitmap.c - the basic definition of the bitmap
4 | *
5 | * IBITMAP is designed under the desire that it can exactly describe
6 | * one basic bitmap, which is considered as simple and pure.
7 | *
8 | * there are five basic bitmap operating interfaces:
9 | *
10 | * create - create a new bitmap and return the struct address
11 | * release - free the bitmap
12 | * blit - copy the speciafied rectangle from one bitmap to another
13 | * setmask - set the color key for transparent blit (IBLIT_MASK on)
14 | * fill - fill a rectange in the bitmap
15 | *
16 | * the history of this file:
17 | * Feb. 7 2003 skywind created including create/release/blit
18 | * Dec. 15 2004 skywind add filling
19 | *
20 | * aim to keep it simply and stupid, this file will only provide the
21 | * most basic bitmap operation interfaces. pixel format declearation,
22 | * color components modification must not be included in it.
23 | *
24 | * aim to platform independence, all of the sources are writen in ansi
25 | * c but you can replace the default blitter by ibitmap_funcset() to
26 | * optimized the benchmark of ibitmap_blit in the speciafied platform
27 | *
28 | **********************************************************************/
29 |
30 | #include "ibitmap.h"
31 |
32 | #include
33 | #include
34 | #include
35 | #include
36 |
37 |
38 | /**********************************************************************
39 | * MEMORY ALLOCATOR FUNCTIONS
40 | **********************************************************************/
41 | void*(*icmalloc)(size_t size) = malloc;
42 | void (*icfree)(void *ptr) = free;
43 |
44 |
45 | /**********************************************************************
46 | * BASIC BITMAP FUNCTIONS
47 | **********************************************************************/
48 |
49 | /*
50 | * ibitmap_create - create bitmap and return the pointer to struct IBITMAP
51 | * width - bitmap width
52 | * height - bitmap height
53 | * bpp - bitmap color depth (8, 16, 24, 32)
54 | */
55 | struct IBITMAP *ibitmap_create(int w, int h, int bpp)
56 | {
57 | struct IBITMAP *bmp;
58 | unsigned char*line;
59 | int pixelbyte = (bpp + 7) >> 3;
60 | int i;
61 |
62 | /* check for invalid parametes */
63 | assert(bpp >= 8 && bpp <=32 && w > 0 && h > 0);
64 |
65 | /* allocate memory for the IBITMAP struct */
66 | bmp = (struct IBITMAP*)icmalloc(sizeof(struct IBITMAP));
67 | if (bmp == NULL) return NULL;
68 |
69 | /* setup bmp struct */
70 | bmp->w = w;
71 | bmp->h= h;
72 | bmp->bpp = bpp;
73 | bmp->pitch = (((long)w * pixelbyte + 7) >> 3) << 3;
74 | bmp->code = 0;
75 |
76 | /* allocate memory for pixel data */
77 | bmp->pixel = (char*)icmalloc(bmp->pitch * h);
78 |
79 | if (bmp->pixel == NULL) {
80 | icfree(bmp);
81 | return NULL;
82 | }
83 |
84 | bmp->mode = 0;
85 | bmp->mask = 0;
86 | bmp->extra = NULL;
87 |
88 | /* caculate the offset of each scanline */
89 | bmp->line = (void**)icmalloc(sizeof(void*) * h);
90 | if (bmp->line == NULL) {
91 | icfree(bmp->pixel);
92 | icfree(bmp);
93 | return NULL;
94 | }
95 |
96 | line = (unsigned char*)bmp->pixel;
97 | for (i = 0; i < h; i++, line += bmp->pitch)
98 | bmp->line[i] = line;
99 |
100 | return bmp;
101 | }
102 |
103 | /*
104 | * ibitmap_release - release bitmap
105 | * bmp - pointer to the IBITMAP struct
106 | */
107 | void ibitmap_release(struct IBITMAP *bmp)
108 | {
109 | assert(bmp);
110 | if (bmp->pixel) icfree(bmp->pixel);
111 | bmp->pixel = NULL;
112 | if (bmp->line) icfree(bmp->line);
113 | bmp->line = NULL;
114 | bmp->w = 0;
115 | bmp->h = 0;
116 | bmp->pitch = 0;
117 | bmp->bpp = 0;
118 | icfree(bmp);
119 | }
120 |
121 |
122 | /*
123 | * ibitmap_clip - clip the rectangle from the src clip and dst clip then
124 | * caculate a new rectangle which is shared between dst and src cliprect:
125 | * clipdst - dest clip array (left, top, right, bottom)
126 | * clipsrc - source clip array (left, top, right, bottom)
127 | * (x, y) - dest position
128 | * rectsrc - source rect
129 | * mode - check IBLIT_HFLIP or IBLIT_VFLIP
130 | * return zero for successful, return non-zero if there is no shared part
131 | */
132 | int ibitmap_clip(const int *clipdst, const int *clipsrc, int *x, int *y,
133 | int *rectsrc, int mode)
134 | {
135 | int dcl = clipdst[0]; /* dest clip: left */
136 | int dct = clipdst[1]; /* dest clip: top */
137 | int dcr = clipdst[2]; /* dest clip: right */
138 | int dcb = clipdst[3]; /* dest clip: bottom */
139 | int scl = clipsrc[0]; /* source clip: left */
140 | int sct = clipsrc[1]; /* source clip: top */
141 | int scr = clipsrc[2]; /* source clip: right */
142 | int scb = clipsrc[3]; /* source clip: bottom */
143 | int dx = *x; /* dest x position */
144 | int dy = *y; /* dest y position */
145 | int sl = rectsrc[0]; /* source rectangle: left */
146 | int st = rectsrc[1]; /* source rectangle: top */
147 | int sr = rectsrc[2]; /* source rectangle: right */
148 | int sb = rectsrc[3]; /* source rectangle: bottom */
149 | int hflip, vflip;
150 | int w, h, d;
151 |
152 | hflip = (mode & IBLIT_HFLIP)? 1 : 0;
153 | vflip = (mode & IBLIT_VFLIP)? 1 : 0;
154 |
155 | if (dcr <= dcl || dcb <= dct || scr <= scl || scb <= sct)
156 | return -1;
157 |
158 | if (sr <= scl || sb <= sct || sl >= scr || st >= scb)
159 | return -2;
160 |
161 | /* check dest clip: left */
162 | if (dx < dcl) {
163 | d = dcl - dx;
164 | dx = dcl;
165 | if (!hflip) sl += d;
166 | else sr -= d;
167 | }
168 |
169 | /* check dest clip: top */
170 | if (dy < dct) {
171 | d = dct - dy;
172 | dy = dct;
173 | if (!vflip) st += d;
174 | else sb -= d;
175 | }
176 |
177 | w = sr - sl;
178 | h = sb - st;
179 |
180 | if (w < 0 || h < 0)
181 | return -3;
182 |
183 | /* check dest clip: right */
184 | if (dx + w > dcr) {
185 | d = dx + w - dcr;
186 | if (!hflip) sr -= d;
187 | else sl += d;
188 | }
189 |
190 | /* check dest clip: bottom */
191 | if (dy + h > dcb) {
192 | d = dy + h - dcb;
193 | if (!vflip) sb -= d;
194 | else st += d;
195 | }
196 |
197 | if (sl >= sr || st >= sb)
198 | return -4;
199 |
200 | /* check source clip: left */
201 | if (sl < scl) {
202 | d = scl - sl;
203 | sl = scl;
204 | if (!hflip) dx += d;
205 | }
206 |
207 | /* check source clip: top */
208 | if (st < sct) {
209 | d = sct - st;
210 | st = sct;
211 | if (!vflip) dy += d;
212 | }
213 |
214 | if (sl >= sr || st >= sb)
215 | return -5;
216 |
217 | /* check source clip: right */
218 | if (sr > scr) {
219 | d = sr - scr;
220 | sr = scr;
221 | if (hflip) dx += d;
222 | }
223 |
224 | /* check source clip: bottom */
225 | if (sb > scb) {
226 | d = sb - scb;
227 | sb = scb;
228 | if (vflip) dy += d;
229 | }
230 |
231 | if (sl >= sr || st >= sb)
232 | return -6;
233 |
234 | *x = dx;
235 | *y = dy;
236 |
237 | rectsrc[0] = sl;
238 | rectsrc[1] = st;
239 | rectsrc[2] = sr;
240 | rectsrc[3] = sb;
241 |
242 | return 0;
243 | }
244 |
245 |
246 | /**********************************************************************
247 | * BLITTER DEFINITION
248 | **********************************************************************/
249 | int ibitmap_blitnc(char *dst, long pitch1, const char *src, long pitch2,
250 | int w, int h, int pixsize, long linesize);
251 | int ibitmap_blitmc(char *dst, long pitch1, const char *src, long pitch2,
252 | int w, int h, int pixsize, long linesize, unsigned long mask);
253 | int ibitmap_blitfc(char *dst, long pitch1, const char *src, long pitch2,
254 | int w, int h, int pixsize, long linesize, unsigned long mask, int flag);
255 |
256 |
257 | /* set blitters interface to default blitters (c version) */
258 | ibitmap_blitter_norm ibitmap_blitn = ibitmap_blitnc;
259 | ibitmap_blitter_mask ibitmap_blitm = ibitmap_blitmc;
260 | ibitmap_blitter_flip ibitmap_blitf = ibitmap_blitfc;
261 |
262 |
263 |
264 | /**********************************************************************
265 | * BLITTER INTERFACE - CORE OPERATION
266 | **********************************************************************/
267 |
268 | /*
269 | * ibitmap_blit - blit from source bitmap to dest bitmap
270 | * returns zero for successful, others for error
271 | * dst - dest bitmap to draw on
272 | * x, y - target position of dest bitmap to draw on
273 | * src - source bitmap
274 | * sx, sy - source rectangle position in source bitmap
275 | * w, h - source rectangle width and height in source bitmap
276 | * mode - blit flag bits (IBLIT_CLIP, IBLIT_MASK)
277 | */
278 | int ibitmap_blit(struct IBITMAP *dst, int x, int y,
279 | const struct IBITMAP *src, int sx, int sy, int w, int h, int mode)
280 | {
281 | long pitch1, pitch2;
282 | long linesize, d1, d2;
283 | int pixsize, r;
284 | char *pixel1;
285 | char *pixel2;
286 |
287 | /* check whether parametes is error */
288 | assert(src && dst);
289 | assert(src->bpp == dst->bpp);
290 |
291 | /* check whether need to clip rectangle */
292 | if (mode & IBLIT_CLIP) {
293 | int clipdst[4], clipsrc[4], rect[4];
294 | clipdst[0] = 0;
295 | clipdst[1] = 0;
296 | clipdst[2] = (int)dst->w;
297 | clipdst[3] = (int)dst->h;
298 | clipsrc[0] = 0;
299 | clipsrc[1] = 0;
300 | clipsrc[2] = (int)src->w;
301 | clipsrc[3] = (int)src->h;
302 | rect[0] = sx;
303 | rect[1] = sy;
304 | rect[2] = sx + (int)w;
305 | rect[3] = sy + (int)h;
306 | r = ibitmap_clip(clipdst, clipsrc, &x, &y, rect, mode);
307 | if (r != 0) return 0;
308 | sx = rect[0];
309 | sy = rect[1];
310 | w = rect[2] - rect[0];
311 | h = rect[3] - rect[1];
312 | }
313 |
314 | /* get the size of one pixel */
315 | pixsize = (src->bpp + 7) >> 3;
316 | pitch1 = dst->pitch;
317 | pitch2 = src->pitch;
318 |
319 | /* choose linear offset */
320 | switch (pixsize) {
321 | case 1:
322 | linesize = w;
323 | d1 = x;
324 | d2 = sx;
325 | break;
326 | case 2:
327 | linesize = (w << 1);
328 | d1 = (x << 1);
329 | d2 = (sx << 1);
330 | break;
331 | case 3:
332 | linesize = (w << 1) + w;
333 | d1 = (x << 1) + x;
334 | d2 = (sx << 1) + sx;
335 | break;
336 | case 4:
337 | linesize = (w << 2);
338 | d1 = (x << 2);
339 | d2 = (sx << 2);
340 | break;
341 | default:
342 | linesize = w * pixsize;
343 | d1 = x * pixsize;
344 | d2 = sx * pixsize;
345 | break;
346 | }
347 |
348 | /* get the first scanlines of two bitmaps */
349 | pixel1 = (char*)dst->line[y] + d1;
350 | pixel2 = (char*)src->line[sy] + d2;
351 |
352 | /* detect whether blit with flip */
353 | if ((mode & (IBLIT_VFLIP | IBLIT_HFLIP)) != 0) {
354 | if (mode & IBLIT_VFLIP) {
355 | pixel2 = (char*)src->line[sy + h - 1] + d2;
356 | }
357 | r = ibitmap_blitf(pixel1, pitch1, pixel2, pitch2, w, h,
358 | pixsize, linesize, src->mask, mode);
359 | if (r) ibitmap_blitfc(pixel1, pitch1, pixel2, pitch2, w, h,
360 | pixsize, linesize, src->mask, mode);
361 | return 0;
362 | }
363 |
364 | /* check to use the normal blitter or the transparent blitter */
365 | if ((mode & IBLIT_MASK) == 0) {
366 | r = ibitmap_blitn(pixel1, pitch1, pixel2, pitch2, w, h,
367 | pixsize, linesize);
368 | if (r) ibitmap_blitnc(pixel1, pitch1, pixel2, pitch2, w, h,
369 | pixsize, linesize);
370 | } else {
371 | r = ibitmap_blitm(pixel1, pitch1, pixel2, pitch2, w, h,
372 | pixsize, linesize, src->mask);
373 | if (r) ibitmap_blitmc(pixel1, pitch1, pixel2, pitch2, w, h,
374 | pixsize, linesize, src->mask);
375 | }
376 |
377 | return 0;
378 | }
379 |
380 |
381 | /**********************************************************************
382 | * ibitmap_blitnc - default blitter for normal blit (no transparent)
383 | **********************************************************************/
384 | int ibitmap_blitnc(char *dst, long pitch1, const char *src, long pitch2,
385 | int w, int h, int pixelbyte, long linesize)
386 | {
387 | char *ss = (char*)src;
388 | char *sd = (char*)dst;
389 |
390 | /* avoid never use warnings */
391 | if (pixelbyte == 1) linesize = w;
392 |
393 | /* copy each line */
394 | for (; h; h--)
395 | {
396 | memcpy(sd, ss, linesize);
397 | sd += pitch1;
398 | ss += pitch2;
399 | }
400 |
401 | return 0;
402 | }
403 |
404 |
405 | /**********************************************************************
406 | * ibitmap_blitmc - default blitter for transparent blit
407 | **********************************************************************/
408 | int ibitmap_blitmc(char *dst, long pitch1, const char *src, long pitch2,
409 | int w, int h, int pixelbyte, long linesize, unsigned long mask)
410 | {
411 | static unsigned long endian = 0x11223344;
412 | unsigned char *p1, *p2;
413 | unsigned long key24, c;
414 | unsigned char key08;
415 | unsigned short key16;
416 | unsigned int imask, k;
417 | long inc1, inc2, i;
418 | long longsize, isize;
419 |
420 | /* caculate the inc offset of two array */
421 | inc1 = pitch1 - linesize;
422 | inc2 = pitch2 - linesize;
423 |
424 | longsize = sizeof(long);
425 | isize = sizeof(int);
426 |
427 | /* copying pixel for all color depth */
428 | switch (pixelbyte)
429 | {
430 | /* for 8 bits colors depth */
431 | case 1:
432 | key08 = (unsigned char)mask;
433 | for (; h; h--) { /* copy each scanline */
434 | for (i = w; i; i--) { /* copy each pixel */
435 | if (*(unsigned char*)src != key08) *dst = *src;
436 | src++;
437 | dst++;
438 | }
439 | dst += inc1;
440 | src += inc2;
441 | }
442 | break;
443 |
444 | /* for 15/16 bits colors depth */
445 | case 2:
446 | key16 = (unsigned short)mask;
447 | for (; h; h--) { /* copy each scanline */
448 | for (i = w; i; i--) { /* copy each pixel */
449 | if (*(unsigned short*)src != key16)
450 | *(unsigned short*)dst = *(unsigned short*)src;
451 | src += 2;
452 | dst += 2;
453 | }
454 | dst += inc1;
455 | src += inc2;
456 | }
457 | break;
458 |
459 | /* for 24 bits colors depth */
460 | case 3:
461 | if (((unsigned char*)&endian)[0] != 0x44) key24 = mask;
462 | else key24 = ((mask & 0xFFFF) << 8) | ((mask >> 16) & 0xFF);
463 | p1 = (unsigned char*)dst;
464 | p2 = (unsigned char*)src;
465 |
466 | /* 32/16 BIT: detect word-size in runtime instead of using */
467 | /* macros, in order to be compiled in any unknown platform */
468 | if (longsize == 4) { /* 32/16 BIT PLATFORM */
469 | for (; h; h--) { /* copy each scanline */
470 | for (i = w; i; i--) { /* copy each pixel */
471 | c = (((unsigned long)(*(unsigned short*)p2)) << 8);
472 | if ((c | p2[2]) != key24) {
473 | p1[0] = p2[0];
474 | p1[1] = p2[1];
475 | p1[2] = p2[2];
476 | }
477 | p1 += 3;
478 | p2 += 3;
479 | }
480 | p1 += inc1;
481 | p2 += inc2;
482 | }
483 | }
484 | else if (isize == 4) { /* 64 BIT PLATFORM */
485 | imask = (unsigned int)(key24 & 0xffffffff);
486 | for (; h; h--) { /* copy each scanline */
487 | for (i = w; i; i--) { /* copy each pixel */
488 | k = (((unsigned int)(*(unsigned short*)p2)) << 8);
489 | if ((k | p2[2]) != imask) {
490 | p1[0] = p2[0];
491 | p1[1] = p2[1];
492 | p1[2] = p2[2];
493 | }
494 | p1 += 3;
495 | p2 += 3;
496 | }
497 | p1 += inc1;
498 | p2 += inc2;
499 | }
500 | }
501 | break;
502 |
503 | /* for 32 bits colors depth */
504 | case 4:
505 | /* 32/16 BIT: detect word-size in runtime instead of using */
506 | /* macros, in order to be compiled in any unknown platform */
507 | if (longsize == 4) { /* 32/16 BIT PLATFORM */
508 | for (; h; h--) { /* copy each scanline */
509 | for (i = w; i; i--) { /* copy each pixel */
510 | if (*(unsigned long*)src != mask)
511 | *(unsigned long*)dst = *(unsigned long*)src;
512 | src += 4;
513 | dst += 4;
514 | }
515 | dst += inc1;
516 | src += inc2;
517 | }
518 | }
519 | else if (isize == 4) { /* 64 BIT PLATFORM */
520 | imask = (unsigned int)(mask & 0xffffffff);
521 | for (; h; h--) { /* copy each scanline */
522 | for (i = w; i; i--) { /* copy each pixel */
523 | if (*(unsigned int*)src != imask)
524 | *(unsigned int*)dst = *(unsigned int*)src;
525 | src += 4;
526 | dst += 4;
527 | }
528 | dst += inc1;
529 | src += inc2;
530 | }
531 | }
532 | break;
533 | }
534 |
535 | return 0;
536 | }
537 |
538 |
539 | /**********************************************************************
540 | * ibitmap_blitfc - default blitter for flip blit
541 | **********************************************************************/
542 | int ibitmap_blitfc(char *dst, long pitch1, const char *src, long pitch2,
543 | int w, int h, int pixsize, long linesize, unsigned long mask, int flag)
544 | {
545 | static unsigned long endian = 0x11223344;
546 | unsigned char *p1, *p2;
547 | unsigned long key24, c;
548 | unsigned char key08;
549 | unsigned short key16;
550 | unsigned int imask, k;
551 | long inc1, inc2, i;
552 | long longsize, isize;
553 |
554 | /* flip vertical without mask */
555 | if ((flag & (IBLIT_MASK | IBLIT_HFLIP)) == 0) {
556 | for (; h; h--) {
557 | memcpy(dst, src, linesize);
558 | dst += pitch1;
559 | src -= pitch2;
560 | }
561 | return 0;
562 | }
563 |
564 | /* flip vertical with mask */
565 | if ((flag & IBLIT_MASK) != 0 && (flag & IBLIT_HFLIP) == 0) {
566 | for (; h; h--) {
567 | ibitmap_blitmc(dst, pitch1, src, pitch2, w, 1, pixsize,
568 | linesize, mask);
569 | dst += pitch1;
570 | src -= pitch2;
571 | }
572 | return 0;
573 | }
574 |
575 | /* flip horizon */
576 | src += linesize - pixsize;
577 | inc1 = pitch1 - linesize;
578 |
579 | longsize = sizeof(long);
580 | isize = sizeof(int);
581 |
582 | /* horizon & vertical or horizon only */
583 | if (flag & IBLIT_VFLIP) inc2 = - (pitch2 - linesize);
584 | else inc2 = pitch2 + linesize;
585 |
586 | /* copying pixel for all color depth */
587 | switch (pixsize)
588 | {
589 | /* flip in 8 bits colors depth */
590 | case 1:
591 | key08 = (unsigned char)mask;
592 | for (; h; h--) {
593 | if (flag & IBLIT_MASK) {
594 | for (i = w; i; i--) { /* copy each pixel with mask */
595 | if (*(unsigned char*)src != key08) *dst = *src;
596 | dst++;
597 | src--;
598 | }
599 | } else {
600 | for (i = w; i; i--) { /* copy pixels without mask */
601 | *dst = *src;
602 | dst++;
603 | src--;
604 | }
605 | }
606 | dst += inc1;
607 | src += inc2;
608 | }
609 | break;
610 |
611 | /* flip in 15/16 bits colors depth */
612 | case 2:
613 | key16 = (unsigned short)mask;
614 | for (; h; h--) {
615 | if (flag & IBLIT_MASK) {
616 | for (i = w; i; i--) { /* copy each pixel with mask */
617 | if (*(unsigned short*)src != key16)
618 | *(unsigned short*)dst = *(unsigned short*)src;
619 | dst += 2;
620 | src -= 2;
621 | }
622 | } else {
623 | for (i = w; i; i--) { /* copy pixels without mask */
624 | *(unsigned short*)dst = *(unsigned short*)src;
625 | dst += 2;
626 | src -= 2;
627 | }
628 | }
629 | dst += inc1;
630 | src += inc2;
631 | }
632 | break;
633 |
634 | /* flip in 24 bits colors depth */
635 | case 3:
636 | if (((unsigned char*)&endian)[0] != 0x44) key24 = mask;
637 | else key24 = ((mask & 0xFFFF) << 8) | ((mask >> 16) & 0xFF);
638 | p1 = (unsigned char*)dst;
639 | p2 = (unsigned char*)src;
640 | for (; h; h--) { /* copy each scanline */
641 | if (flag & IBLIT_MASK) {
642 | if (longsize == 4) { /* 32/16 BIT PLATFORM */
643 | for (i = w; i; i--) { /* copy each pixel with mask */
644 | c = (((unsigned long)(*(unsigned short*)p2)) << 8);
645 | if ((c | p2[2]) != key24) {
646 | p1[0] = p2[0];
647 | p1[1] = p2[1];
648 | p1[2] = p2[2];
649 | }
650 | p1 += 3;
651 | p2 -= 3;
652 | }
653 | }
654 | else if (isize == 4) { /* 64 BIT PLATFORM */
655 | imask = (unsigned int)(key24 & 0xffffffff);
656 | for (i = w; i; i--) { /* copy each pixel with mask */
657 | k = (((unsigned int)(*(unsigned short*)p2)) << 8);
658 | if ((k | p2[2]) != imask) {
659 | p1[0] = p2[0];
660 | p1[1] = p2[1];
661 | p1[2] = p2[2];
662 | }
663 | p1 += 3;
664 | p2 -= 3;
665 | }
666 | }
667 | } else { /* copy pixels without mask */
668 | for (i = w; i; i--) {
669 | p1[0] = p2[0];
670 | p1[1] = p2[1];
671 | p1[2] = p2[2];
672 | p1 += 3;
673 | p2 -= 3;
674 | }
675 | }
676 | p1 += inc1;
677 | p2 += inc2;
678 | }
679 | break;
680 |
681 | /* flip in 32 bits colors depth */
682 | case 4:
683 | for (; h; h--) {
684 | if (longsize == 4) { /* 32/16 BIT PLATFORM */
685 | if (flag & IBLIT_MASK) {
686 | for (i = w; i; i--) { /* copy each pixel with mask */
687 | if (*(unsigned long*)src != mask)
688 | *(unsigned long*)dst = *(unsigned long*)src;
689 | dst += 4;
690 | src -= 4;
691 | }
692 | } else {
693 | for (i = w; i; i--) { /* copy pixels without mask */
694 | *(unsigned long*)dst = *(unsigned long*)src;
695 | dst += 4;
696 | src -= 4;
697 | }
698 | }
699 | }
700 | else if (isize == 4) { /* 64 BIT PLATFORM */
701 | imask = (unsigned int)(mask & 0xffffffff);
702 | if (flag & IBLIT_MASK) {
703 | for (i = w; i; i--) { /* copy each pixel with mask */
704 | if (*(unsigned int*)src != imask)
705 | *(unsigned int*)dst = *(unsigned int*)src;
706 | dst += 4;
707 | src -= 4;
708 | }
709 | } else {
710 | for (i = w; i; i--) { /* copy pixels without mask */
711 | *(unsigned int*)dst = *(unsigned int*)src;
712 | dst += 4;
713 | src -= 4;
714 | }
715 | }
716 | }
717 | dst += inc1;
718 | src += inc2;
719 | }
720 | break;
721 | }
722 |
723 | return 0;
724 | }
725 |
726 |
727 |
728 | /*
729 | * ibitmap_setmask - change mask(colorkey) of the bitmap
730 | * when blit with IBLIT_MASK, this value can be used as the key color to
731 | * transparent. you can change bmp->mask directly without calling it.
732 | */
733 | int ibitmap_setmask(struct IBITMAP *bmp, unsigned long mask)
734 | {
735 | bmp->mask = mask;
736 | return 0;
737 | }
738 |
739 |
740 | /**********************************************************************
741 | * FILLER DEFINITION
742 | **********************************************************************/
743 | int ibitmap_fillc(char *dst, long pitch, int w, int h, int pixsize,
744 | unsigned long c);
745 |
746 | /* set filler interface to default filler (c version) */
747 | ibitmap_filler ibitmap_filling = ibitmap_fillc;
748 |
749 |
750 | /* ibitmap_fill - fill the rectangle with given color
751 | * returns zero for successful, others for error
752 | * dst - dest bitmap to draw on
753 | * dx, dy - target position of dest bitmap to draw on
754 | * w, h - width and height of the rectangle to be filled
755 | * col - indicate the color to fill the rectangle
756 | */
757 | int ibitmap_fill(struct IBITMAP *dst, int dx, int dy, int w, int h,
758 | unsigned long col, int noclip)
759 | {
760 | int pixsize, r;
761 | long delta;
762 | char *pixel;
763 |
764 | assert(dst);
765 | if (noclip == 0) {
766 | if (dx >= (long)dst->w || dx + w <= 0 || w < 0) return 0;
767 | if (dy >= (long)dst->h || dy + h <= 0 || h < 0) return 0;
768 | if (dx < 0) w += dx, dx = 0;
769 | if (dy < 0) h += dy, dy = 0;
770 | if (dx + w >= (long)dst->w) w = (long)dst->w - dx;
771 | if (dy + h >= (long)dst->h) h = (long)dst->h - dy;
772 | }
773 |
774 | /* get pixel size */
775 | pixsize = (dst->bpp + 7) >> 3;
776 |
777 | /* choose linear offset */
778 | switch (pixsize) {
779 | case 1: delta = dx; break;
780 | case 2: delta = (dx << 1); break;
781 | case 3: delta = (dx << 1) + dx; break;
782 | case 4: delta = (dx << 2); break;
783 | default: delta = dx * pixsize; break;
784 | }
785 |
786 | /* get the first scanlines of the bitmap */
787 | pixel = (char*)dst->line[dy] + delta;
788 |
789 | r = ibitmap_filling(pixel, dst->pitch, w, h, pixsize, col);
790 | if (r) ibitmap_fillc(pixel, dst->pitch, w, h, pixsize, col);
791 |
792 | return 0;
793 | }
794 |
795 |
796 | /**********************************************************************
797 | * ibitmap_blitfc - default blitter for flip blit
798 | **********************************************************************/
799 | int ibitmap_fillc(char *dst, long pitch, int w, int h, int pixsize,
800 | unsigned long col)
801 | {
802 | static unsigned long endian = 0x11223344;
803 | unsigned short col16;
804 | unsigned char col8, c1, c2, c3;
805 | unsigned long *p32;
806 | unsigned int k, *k32;
807 | long longsize, isize;
808 | long inc, i;
809 |
810 | longsize = sizeof(long);
811 | isize = sizeof(int);
812 |
813 | switch (pixsize)
814 | {
815 | /* fill for 8 bits color depth */
816 | case 1:
817 | col8 = (unsigned char)(col & 0xff);
818 | for (; h; h--) {
819 | memset(dst, col8, w);
820 | dst += pitch;
821 | }
822 | break;
823 |
824 | /* fill for 15/16 bits color depth */
825 | case 2:
826 | col16 = (unsigned short)(col & 0xffff);
827 | col = (col << 16) | (col & 0xffff);
828 | if (longsize == 4) { /* 32/16 BIT PLATFORM */
829 | for (; h; h--) {
830 | p32 = (unsigned long*)dst;
831 | for (i = w >> 1; i; i--) *p32++ = col;
832 | if (w & 1) *(unsigned short*)p32 = col16;
833 | dst += pitch;
834 | }
835 | }
836 | else if (isize == 4) { /* 64 BIT PLATFORM */
837 | k = (unsigned int)(col & 0xffffffff);
838 | for (; h; h--) {
839 | k32 = (unsigned int*)dst;
840 | for (i = w >> 1; i; i--) *k32++ = k;
841 | if (w & 1) *(unsigned short*)k32 = col16;
842 | dst += pitch;
843 | }
844 | }
845 | break;
846 |
847 | /* fill for 24 bits color depth */
848 | case 3:
849 | inc = pitch - ((w << 1) + w);
850 | if (((unsigned char*)&endian)[0] != 0x44) {
851 | c1 = (unsigned char)((col >> 16) & 0xff);
852 | c2 = (unsigned char)((col >> 8) & 0xff);
853 | c3 = (unsigned char)(col & 0xff);
854 | } else {
855 | c1 = (unsigned char)(col & 0xff);
856 | c2 = (unsigned char)((col >> 8) & 0xff);
857 | c3 = (unsigned char)((col >> 16) & 0xff);
858 | }
859 | for (; h; h--) {
860 | for (i = w; i; i--) {
861 | *dst++ = c1;
862 | *dst++ = c2;
863 | *dst++ = c3;
864 | }
865 | dst += inc;
866 | }
867 | break;
868 |
869 | /* fill for 32 bits color depth */
870 | case 4:
871 | if (longsize == 4) { /* 32/16 BIT PLATFORM */
872 | for (; h; h--) {
873 | p32 = (unsigned long*)dst;
874 | for (i = w; i; i--) *p32++ = col;
875 | dst += pitch;
876 | }
877 | }
878 | else if (isize == 4) { /* 64 BIT PLATFORM */
879 | k = (unsigned int)(col & 0xffffffff);
880 | for (; h; h--) {
881 | k32 = (unsigned int*)dst;
882 | for (i = w; i; i--) *k32++ = k;
883 | dst += pitch;
884 | }
885 | }
886 | break;
887 | }
888 |
889 | return 0;
890 | }
891 |
892 |
893 | /* ibitmap_stretch - copies a bitmap from a source rectangle into a
894 | * destination rectangle, stretching or compressing the bitmap to fit
895 | * the dimensions of the destination rectangle
896 | * returns zero for successful, others for invalid rectangle
897 | * dst - dest bitmap to draw on
898 | * dx, dy - target rectangle position of dest bitmap to draw on
899 | * dw, dh - target rectangle width and height in dest bitmap
900 | * src - source bitmap
901 | * sx, sy - source rectangle position in source bitmap
902 | * sw, sh - source rectangle width and height in source bitmap
903 | * mode - flags of IBLIT_MASK, IBLIT_HFLIP, IBLIT_VFLIP...
904 | * it uses bresenham like algorithm instead of fixed point or indexing
905 | * to avoid integer size overflow and memory allocation, just use it
906 | * when you don't have a stretch function.
907 | */
908 | int ibitmap_stretch(struct IBITMAP *dst, int dx, int dy, int dw, int dh,
909 | const struct IBITMAP *src, int sx, int sy, int sw, int sh, int mode)
910 | {
911 | int dstwidth, dstheight, dstwidth2, dstheight2, srcwidth2, srcheight2;
912 | int werr, herr, incx, incy, i, j, nbytes;
913 | static unsigned long endian = 0x11223344;
914 | unsigned long mask, key24;
915 | long longsize, isize;
916 |
917 | /* check whether parametes is error */
918 | assert(src && dst);
919 | assert(src->bpp == dst->bpp);
920 |
921 | if (src->bpp != dst->bpp)
922 | return -10;
923 |
924 | if (dw == sw && dh == sh) {
925 | mode |= IBLIT_CLIP;
926 | return ibitmap_blit(dst, dx, dy, src, sx, sy, sw, sh, mode);
927 | }
928 |
929 | if (dx < 0 || dx + dw > (int)dst->w || dy < 0 || dy + dh > (int)dst->h ||
930 | sx < 0 || sx + sw > (int)src->w || sy < 0 || sy + sh > (int)src->h ||
931 | sh <= 0 || sw <= 0 || dh <= 0 || dw <= 0)
932 | return -20;
933 |
934 | dstwidth = dw;
935 | dstheight = dh;
936 | dstwidth2 = dw * 2;
937 | dstheight2 = dh * 2;
938 | srcwidth2 = sw * 2;
939 | srcheight2 = sh * 2;
940 |
941 | if (mode & IBLIT_VFLIP) sy = sy + sh - 1, incy = -1;
942 | else incy = 1;
943 |
944 | herr = srcheight2 - dstheight2;
945 | nbytes = (src->bpp + 7) / 8;
946 |
947 | isize = sizeof(int);
948 | longsize = sizeof(long);
949 | mask = (unsigned long)src->mask;
950 |
951 | for (j = 0; j < dstheight; j++) {
952 | const unsigned char *srcrow = (const unsigned char*)src->line[sy];
953 | unsigned char *dstrow = (unsigned char*)dst->line[dy];
954 | const unsigned char *srcpix = srcrow + nbytes * sx;
955 | unsigned char *dstpix = dstrow + nbytes * dx;
956 | incx = nbytes;
957 | if (mode & IBLIT_HFLIP) {
958 | srcpix += (sw - 1) * nbytes;
959 | incx = -nbytes;
960 | }
961 | werr = srcwidth2 - dstwidth2;
962 |
963 | switch (nbytes)
964 | {
965 | case 1:
966 | {
967 | unsigned char mask8;
968 | if ((mode & IBLIT_MASK) == 0) {
969 | for (i = dstwidth; i > 0; i--) {
970 | *dstpix++ = *srcpix;
971 | while (werr >= 0) {
972 | srcpix += incx, werr -= dstwidth2;
973 | }
974 | werr += srcwidth2;
975 | }
976 | } else {
977 | mask8 = (unsigned char)(src->mask & 0xff);
978 | for (i = dstwidth; i > 0; i--) {
979 | if (*srcpix != mask8) *dstpix = *srcpix;
980 | dstpix++;
981 | while (werr >= 0) {
982 | srcpix += incx, werr -= dstwidth2;
983 | }
984 | werr += srcwidth2;
985 | }
986 | }
987 | }
988 | break;
989 |
990 | case 2:
991 | {
992 | unsigned short mask16;
993 | if ((mode & IBLIT_MASK) == 0) {
994 | for (i = dstwidth; i > 0; i--) {
995 | *((unsigned short*)dstpix) =
996 | *((unsigned short*)srcpix);
997 | dstpix += 2;
998 | while (werr >= 0) {
999 | srcpix += incx, werr -= dstwidth2;
1000 | }
1001 | werr += srcwidth2;
1002 | }
1003 | } else {
1004 | mask16 = (unsigned short)(src->mask & 0xffff);
1005 | for (i = dstwidth; i > 0; i--) {
1006 | if (*((unsigned short*)srcpix) != mask16)
1007 | *((unsigned short*)dstpix) =
1008 | *((unsigned short*)srcpix);
1009 | dstpix += 2;
1010 | while (werr >= 0) {
1011 | srcpix += incx, werr -= dstwidth2;
1012 | }
1013 | werr += srcwidth2;
1014 | }
1015 | }
1016 | }
1017 | break;
1018 |
1019 | case 3:
1020 | if (((unsigned char*)&endian)[0] != 0x44) key24 = mask;
1021 | else key24 = ((mask & 0xFFFF) << 8) | ((mask >> 16) & 0xFF);
1022 | if ((mode & IBLIT_MASK) == 0) {
1023 | for (i = dstwidth; i > 0; i--) {
1024 | dstpix[0] = srcpix[0];
1025 | dstpix[1] = srcpix[1];
1026 | dstpix[2] = srcpix[2];
1027 | dstpix += 3;
1028 | while (werr >= 0) {
1029 | srcpix += incx, werr -= dstwidth2;
1030 | }
1031 | werr += srcwidth2;
1032 | }
1033 | }
1034 | else if (longsize == 4) {
1035 | unsigned long longmask, k;
1036 | longmask = key24 & 0xffffff;
1037 | for (i = dstwidth; i > 0; i--) {
1038 | k = (((unsigned long)(*(unsigned short*)srcpix)) << 8);
1039 | if ((k | srcpix[2]) != longmask) {
1040 | dstpix[0] = srcpix[0];
1041 | dstpix[1] = srcpix[1];
1042 | dstpix[2] = srcpix[2];
1043 | }
1044 | dstpix += 3;
1045 | while (werr >= 0) {
1046 | srcpix += incx, werr -= dstwidth2;
1047 | }
1048 | werr += srcwidth2;
1049 | }
1050 | }
1051 | else if (isize == 4) {
1052 | unsigned int imask, k;
1053 | imask = key24 & 0xffffff;
1054 | for (i = dstwidth; i > 0; i--) {
1055 | k = (((unsigned int)(*(unsigned short*)srcpix)) << 8);
1056 | if ((k | srcpix[2]) != imask) {
1057 | dstpix[0] = srcpix[0];
1058 | dstpix[1] = srcpix[1];
1059 | dstpix[2] = srcpix[2];
1060 | }
1061 | dstpix += 3;
1062 | while (werr >= 0) {
1063 | srcpix += incx, werr -= dstwidth2;
1064 | }
1065 | werr += srcwidth2;
1066 | }
1067 | }
1068 | break;
1069 |
1070 | case 4:
1071 | if (longsize == 4) {
1072 | unsigned long masklong;
1073 | if ((mode & IBLIT_MASK) == 0) {
1074 | for (i = dstwidth; i > 0; i--) {
1075 | *((unsigned long*)dstpix) =
1076 | *((unsigned long*)srcpix);
1077 | dstpix += 4;
1078 | while (werr >= 0) {
1079 | srcpix += incx, werr -= dstwidth2;
1080 | }
1081 | werr += srcwidth2;
1082 | }
1083 | } else {
1084 | masklong = (unsigned long)(src->mask);
1085 | for (i = dstwidth; i > 0; i--) {
1086 | if (*((unsigned long*)srcpix) != masklong)
1087 | *((unsigned long*)dstpix) =
1088 | *((unsigned long*)srcpix);
1089 | dstpix += 4;
1090 | while (werr >= 0) {
1091 | srcpix += incx, werr -= dstwidth2;
1092 | }
1093 | werr += srcwidth2;
1094 | }
1095 | }
1096 | }
1097 | else if (isize == 4) {
1098 | unsigned int maskint;
1099 | if ((mode & IBLIT_MASK) == 0) {
1100 | for (i = dstwidth; i > 0; i--) {
1101 | *((unsigned int*)dstpix) = *((unsigned int*)srcpix);
1102 | dstpix += 4;
1103 | while (werr >= 0) {
1104 | srcpix += incx, werr -= dstwidth2;
1105 | }
1106 | werr += srcwidth2;
1107 | }
1108 | } else {
1109 | maskint = (unsigned int)(src->mask);
1110 | for (i = dstwidth; i > 0; i--) {
1111 | if (*((unsigned int*)srcpix) != maskint)
1112 | *((unsigned int*)dstpix) =
1113 | *((unsigned int*)srcpix);
1114 | dstpix += 4;
1115 | while (werr >= 0) {
1116 | srcpix += incx, werr -= dstwidth2;
1117 | }
1118 | werr += srcwidth2;
1119 | }
1120 | }
1121 | }
1122 | else {
1123 | assert(0);
1124 | }
1125 | break;
1126 | }
1127 |
1128 | while (herr >= 0) {
1129 | sy += incy, herr -= dstheight2;
1130 | }
1131 |
1132 | herr += srcheight2;
1133 | dy++;
1134 | }
1135 |
1136 | return 0;
1137 | }
1138 |
1139 |
1140 |
1141 | /*
1142 | * ibitmap_funcset - set basic bitmap functions, returns zero for successful
1143 | * mode - function index, there are two blitters, (0/1 normal/transparent)
1144 | * proc - extra function pointer, set it to null to use default method
1145 | * there are two blitters, normal blitter and transparent blitter, which
1146 | * ibitmap_blit will call to complete blit operation. see ibitmapm.c
1147 | */
1148 | int ibitmap_funcset(int functionid, const void *proc)
1149 | {
1150 | typedef void*(*icmalloc_t)(size_t);
1151 | typedef void (*icfree_t)(void*ptr);
1152 |
1153 | switch (functionid)
1154 | {
1155 | case IBITMAP_BLITER_NORM:
1156 | ibitmap_blitn = (proc == NULL)? ibitmap_blitnc :
1157 | (ibitmap_blitter_norm)proc;
1158 | break;
1159 | case IBITMAP_BLITER_MASK:
1160 | ibitmap_blitm = (proc == NULL)? ibitmap_blitmc :
1161 | (ibitmap_blitter_mask)proc;
1162 | break;
1163 | case IBITMAP_BLITER_FLIP:
1164 | ibitmap_blitf = (proc == NULL)? ibitmap_blitfc :
1165 | (ibitmap_blitter_flip)proc;
1166 | break;
1167 | case IBITMAP_FILLER:
1168 | ibitmap_filling = (proc == NULL)? ibitmap_fillc :
1169 | (ibitmap_filler)proc;
1170 | break;
1171 | case IBITMAP_MALLOC:
1172 | icmalloc = (proc == NULL)? malloc : (icmalloc_t)proc;
1173 | break;
1174 | case IBITMAP_FREE:
1175 | icfree = (proc == NULL)? free : (icfree_t)proc;
1176 | break;
1177 | default:
1178 | assert(0);
1179 | break;
1180 | }
1181 | return 0;
1182 | }
1183 |
1184 |
1185 | /*
1186 | * ibitmap_funcget - get the blitter function pointer, returns the address
1187 | * of the blitter function, and returns NULL for error. for more information
1188 | * please see the comment of ibitmap_funcset.
1189 | */
1190 | void *ibitmap_funcget(int functionid, int version)
1191 | {
1192 | void *proc = NULL;
1193 | switch (functionid)
1194 | {
1195 | case IBITMAP_BLITER_NORM:
1196 | proc = (version)? (void*)ibitmap_blitnc : (void*)ibitmap_blitn;
1197 | break;
1198 | case IBITMAP_BLITER_MASK:
1199 | proc = (version)? (void*)ibitmap_blitmc : (void*)ibitmap_blitm;
1200 | break;
1201 | case IBITMAP_BLITER_FLIP:
1202 | proc = (version)? (void*)ibitmap_blitfc : (void*)ibitmap_blitf;
1203 | break;
1204 | case IBITMAP_FILLER:
1205 | proc = (version)? (void*)ibitmap_fillc : (void*)ibitmap_filling;
1206 | break;
1207 | }
1208 | return proc;
1209 | }
1210 |
1211 |
1212 |
--------------------------------------------------------------------------------
/pixellib/ibitmap.h:
--------------------------------------------------------------------------------
1 | /**********************************************************************
2 | *
3 | * ibitmap.h - the basic definition of the bitmap
4 | *
5 | * IBITMAP is designed under the desire that it can exactly describe
6 | * one basic bitmap, which is considered as simple and pure.
7 | *
8 | * there are five basic bitmap operating interfaces:
9 | *
10 | * create - create a new bitmap and return the struct address
11 | * release - free the bitmap
12 | * blit - copy the speciafied rectangle from one bitmap to another
13 | * setmask - set the color key for transparent blit (IBLIT_MASK on)
14 | * fill - fill a rectange in the bitmap
15 | *
16 | * the history of this file:
17 | * Feb. 7 2003 skywind created including create/release/blit
18 | * Dec. 15 2004 skywind add filling
19 | *
20 | * aim to keep it simply and stupid, this file will only provide the
21 | * most basic bitmap operation interfaces. pixel format declearation,
22 | * color components modification must not be included in it.
23 | *
24 | * aim to platform independence, all of the sources are writen in ansi
25 | * c but you can replace the default blitter by ibitmap_funcset() to
26 | * optimized the benchmark of ibitmap_blit in the speciafied platform
27 | *
28 | **********************************************************************/
29 |
30 | #ifndef __IBITMAP_H__
31 | #define __IBITMAP_H__
32 |
33 |
34 | /**********************************************************************
35 | * IBITMAP DECLEARATION
36 | **********************************************************************/
37 |
38 | struct IBITMAP
39 | {
40 | unsigned long w; /* width of the bitmap */
41 | unsigned long h; /* height of the bitmap */
42 | unsigned long bpp; /* color depth of bitmap */
43 | unsigned long pitch; /* pitch of the bitmap */
44 | unsigned long mask; /* bitmap bit flags */
45 | unsigned long mode; /* additional mode data */
46 | unsigned long code; /* bitmap class code */
47 | void *pixel; /* pixels data in bitmap */
48 | void *extra; /* extra data structure */
49 | void **line; /* pointer to each line in bitmap */
50 | };
51 |
52 |
53 |
54 | /**********************************************************************
55 | * Bitmap Global Interface
56 | **********************************************************************/
57 | #ifndef IBLIT_CLIP
58 | #define IBLIT_CLIP 1 /* blit mode: enable clip */
59 | #endif
60 |
61 | #ifndef IBLIT_MASK
62 | #define IBLIT_MASK 2 /* blit mode: enable transparent blit */
63 | #endif
64 |
65 | #ifndef IBLIT_HFLIP
66 | #define IBLIT_HFLIP 4 /* flip horizon */
67 | #endif
68 |
69 | #ifndef IBLIT_VFLIP
70 | #define IBLIT_VFLIP 8 /* flip vertical */
71 | #endif
72 |
73 |
74 | #ifdef __cplusplus
75 | extern "C" {
76 | #endif
77 |
78 |
79 |
80 | /**********************************************************************
81 | * Bitmap Function Definition
82 | **********************************************************************/
83 |
84 | /*
85 | * ibitmap_create - create bitmap and return the pointer to struct IBITMAP
86 | * width - bitmap width
87 | * height - bitmap height
88 | * bpp - bitmap color depth (8, 16, 24, 32)
89 | */
90 | struct IBITMAP *ibitmap_create(int width, int height, int bpp);
91 |
92 |
93 | /*
94 | * ibitmap_release - release bitmap
95 | * bmp - pointer to the IBITMAP struct
96 | */
97 | void ibitmap_release(struct IBITMAP *bmp);
98 |
99 |
100 | /*
101 | * ibitmap_clip - clip the rectangle from the src clip and dst clip then
102 | * caculate a new rectangle which is shared between dst and src cliprect:
103 | * clipdst - dest clip array (left, top, right, bottom)
104 | * clipsrc - source clip array (left, top, right, bottom)
105 | * (x, y) - dest position
106 | * rectsrc - source rect
107 | * mode - check IBLIT_HFLIP or IBLIT_VFLIP
108 | * return zero for successful, return non-zero if there is no shared part
109 | */
110 | int ibitmap_clip(const int *clipdst, const int *clipsrc, int *x, int *y,
111 | int *rectsrc, int mode);
112 |
113 |
114 | /*
115 | * ibitmap_blit - blit from source bitmap to dest bitmap
116 | * returns zero for successful, others for error
117 | * dst - dest bitmap to draw on
118 | * x, y - target position of dest bitmap to draw on
119 | * src - source bitmap
120 | * sx, sy - source rectangle position in source bitmap
121 | * w, h - source rectangle width and height in source bitmap
122 | * mode - flags of IBLIT_CLIP, IBLIT_MASK, IBLIT_HFLIP, IBLIT_VFLIP...
123 | */
124 | int ibitmap_blit(struct IBITMAP *dst, int x, int y,
125 | const struct IBITMAP *src, int sx, int sy, int w, int h, int mode);
126 |
127 |
128 | /*
129 | * ibitmap_setmask - change mask(colorkey) of the bitmap
130 | * when blit with IBLIT_MASK, this value can be used as the key color to
131 | * transparent. you can change bmp->mask directly without calling it.
132 | */
133 | int ibitmap_setmask(struct IBITMAP *bmp, unsigned long mask);
134 |
135 |
136 | /* ibitmap_fill - fill the rectangle with given color
137 | * returns zero for successful, others for error
138 | * dst - dest bitmap to draw on
139 | * dx, dy - target position of dest bitmap to draw on
140 | * w, h - width and height of the rectangle to be filled
141 | * col - indicate the color to fill the rectangle
142 | */
143 | int ibitmap_fill(struct IBITMAP *dst, int dx, int dy, int w, int h,
144 | unsigned long col, int noclip);
145 |
146 |
147 | /* ibitmap_stretch - copies a bitmap from a source rectangle into a
148 | * destination rectangle, stretching or compressing the bitmap to fit
149 | * the dimensions of the destination rectangle
150 | * returns zero for successful, others for invalid rectangle
151 | * dst - dest bitmap to draw on
152 | * dx, dy - target rectangle position of dest bitmap to draw on
153 | * dw, dh - target rectangle width and height in dest bitmap
154 | * src - source bitmap
155 | * sx, sy - source rectangle position in source bitmap
156 | * sw, sh - source rectangle width and height in source bitmap
157 | * mode - flags of IBLIT_MASK, IBLIT_HFLIP, IBLIT_VFLIP...
158 | * it uses bresenham like algorithm instead of fixed point or indexing
159 | * to avoid integer size overflow and memory allocation, just use it
160 | * when you don't have a stretch function.
161 | */
162 | int ibitmap_stretch(struct IBITMAP *dst, int dx, int dy, int dw, int dh,
163 | const struct IBITMAP *src, int sx, int sy, int sw, int sh, int mode);
164 |
165 |
166 | /**********************************************************************
167 | * Bitmap Basic Interface
168 | **********************************************************************/
169 | typedef int (*ibitmap_blitter_norm)(char *, long, const char *, long,
170 | int, int, int, long);
171 | typedef int (*ibitmap_blitter_mask)(char *, long, const char *, long,
172 | int, int, int, long, unsigned long);
173 |
174 | typedef int (*ibitmap_blitter_flip)(char *, long, const char *, long,
175 | int, int, int, long, unsigned long, int);
176 |
177 | typedef int (*ibitmap_filler)(char *, long, int, int, int, unsigned long);
178 |
179 |
180 | #define IBITMAP_BLITER_NORM 0
181 | #define IBITMAP_BLITER_MASK 1
182 | #define IBITMAP_BLITER_FLIP 2
183 |
184 | #define IBITMAP_FILLER 3
185 |
186 | #define IBITMAP_MALLOC 4
187 | #define IBITMAP_FREE 5
188 |
189 |
190 |
191 | /*
192 | * ibitmap_funcset - set basic bitmap functions, returns zero for successful
193 | * mode - function index, there are two blitters, (0/1 normal/transparent)
194 | * proc - extra function pointer, set it to null to use default method:
195 | * int imyblitter0(char *dst, long pitch1, const char *src, long pitch2,
196 | * int w, int h, int pixelbyte, long linesize);
197 | * int imyblitter1(char *dst, long pitch1, const char *src, long pitch2
198 | * int w, int h, int pixelbyte, unsigned long mask, long linesize);
199 | * there are two blitters, normal blitter and transparent blitter, which
200 | * ibitmap_blit() will call to complete blit operation.
201 | */
202 | int ibitmap_funcset(int functionid, const void *proc);
203 |
204 |
205 | /*
206 | * ibitmap_funcget - get the blitter function pointer, returns the address
207 | * of the blitter function, and returns NULL for error. for more information
208 | * please see the comment of ibitmap_funcset.
209 | */
210 | void *ibitmap_funcget(int functionid, int version);
211 |
212 |
213 | #ifdef __cplusplus
214 | }
215 | #endif
216 |
217 |
218 | #endif
219 |
220 |
221 |
222 |
--------------------------------------------------------------------------------
/pixellib/iblit386.h:
--------------------------------------------------------------------------------
1 | //=====================================================================
2 | //
3 | // iblit386.h - bitmap blitters implemention in i386
4 | //
5 | // - bypasse on-chip, write directly into combining buffer
6 | // - software prefetch instruction
7 | // - improvement: speed up 200% - 250% vs tradition blitters
8 | // - compile it with gcc, msvc, borlandc, watcomc, ...
9 | //
10 | // for more information about cache-control instructions please see:
11 | // The IA-32 Intel Architecture Software Developer's Manual
12 | // Volume 3: System Programming Guide
13 | // with the URL below:
14 | // http://developer.intel.com/design/pentium4/manuals/253668.htm
15 | // Using Block Prefetch for Optimized Memory Performance, Mike Wall
16 | //
17 | // history of this file:
18 | // - Feb.15 2004 skywind create this file with iblit_386, iblit_mmx
19 | // - Feb.20 2004 skywind add most i386 assembler globals
20 | // - Jun.17 2004 skywind implement normal blitter with sse
21 | // - May.05 2005 skywind implement mask blitter with mmx & sse
22 | // - Aug.02 2005 skywind improve blitters with cache-control tech.
23 | // - Dec.11 2006 skywind rewrite cpu detection method
24 | // - Dec.27 2006 skywind rewrite mask blitters
25 | // - Jan.28 2007 skywind reform this file with new comment
26 | // - Sep.09 2010 skywind add 64bits & mmx macros
27 | // - Oct.03 2010 skywind amd64 supported
28 | //
29 | //=====================================================================
30 |
31 | #ifndef __IBLIT386_H__
32 | #define __IBLIT386_H__
33 |
34 | #include
35 |
36 |
37 | //---------------------------------------------------------------------
38 | // platform detection
39 | //---------------------------------------------------------------------
40 | #if (defined(_WIN32) && !defined(WIN32))
41 | #define WIN32 _WIN32
42 | #elif (defined(WIN32) && !defined(_WIN32))
43 | #define _WIN32 WIN32
44 | #endif
45 |
46 | #if (defined(_WIN32) && !defined(_MSC_VER) && !defined(_WIN64))
47 | #ifndef __i386__
48 | #define __i386__
49 | #endif
50 | #elif defined(_MSC_VER)
51 | #if (defined(_M_IX86) && !defined(__i386__))
52 | #define __i386__
53 | #endif
54 | #endif
55 |
56 | #ifndef __i386__
57 | #if (defined(__386__) || defined(__I386__) || _M_IX86)
58 | #define __i386__
59 | #endif
60 | #endif
61 |
62 | #if (defined(__i386__) && !defined(__I386__))
63 | #define __I386__
64 | #endif
65 |
66 | #if (defined(__x86_64__) && !defined(__x86_64))
67 | #define __x86_64
68 | #endif
69 |
70 | #if (defined(__x86_64) && !defined(__x86_64__))
71 | #define __x86_64__
72 | #endif
73 |
74 | #if (defined(_M_AMD64)) && (!defined(__amd64__))
75 | #define __amd64__
76 | #endif
77 |
78 | #if (defined(__amd64) && !defined(__amd64__))
79 | #define __amd64__
80 | #endif
81 |
82 | #if (defined(__amd64__) && !defined(__amd64))
83 | #define __amd64
84 | #endif
85 |
86 | #if (defined(__i386__) || defined(__amd64__)) && (!defined(__x86__))
87 | #if !(defined(_MSC_VER) && defined(__amd64__))
88 | #define __x86__ // MSVC doesn't support inline assembly in x64
89 | #endif
90 | #endif
91 |
92 | //=====================================================================
93 | // i386 archtech support
94 | //=====================================================================
95 | #ifdef __x86__
96 |
97 |
98 | #ifndef ASMCODE
99 | #define ASMCODE
100 | //---------------------------------------------------------------------
101 | // basic inline asm operation code generation
102 | //---------------------------------------------------------------------
103 | #ifdef __GNUC__
104 | #define ASMCODE1(a) ".byte "#a"\n"
105 | #define ASMCODE2(a, b) ".byte "#a", "#b"\n"
106 | #define ASMCODE3(a, b, c) ".byte "#a", "#b", "#c"\n"
107 | #define ASMCODE4(a, b, c, d) ".byte "#a", "#b", "#c", "#d"\n"
108 | #define ASMCODE5(a, b, c, d, e) ".byte "#a", "#b", "#c", "#d", "#e"\n"
109 | #define ASMCODEW(n) ".short "#n"\n"
110 | #define ASMCODED(n) ".long "#n"\n"
111 | #define ASMALIGN(n) ".align "#n", 0x90\n"
112 | #define __ALIGNC__ ASMALIGN(8)
113 | #define __INLINEGNU__
114 | #ifndef __MACH__
115 | #define ASM_BEGIN
116 | #define ASM_ENDUP
117 | #ifdef __i386__
118 | #define ASM_REGS "esi", "edi", "eax", "ebx", "ecx", "edx"
119 | #else
120 | #define ASM_REGS "rsi", "rdi", "rax", "rbx", "rcx", "rdx"
121 | #endif
122 | #else
123 | #ifdef __i386__
124 | #define ASM_BEGIN " pushl %%ebx\n"
125 | #define ASM_ENDUP " popl %%ebx\n"
126 | #define ASM_REGS "esi", "edi", "eax", "ecx", "edx"
127 | #else
128 | #define ASM_BEGIN " push %%rbx\n"
129 | #define ASM_ENDUP " pop %%rbx\n"
130 | #define ASM_REGS "rsi", "rdi", "rax", "rcx", "rdx"
131 | #endif
132 | #endif
133 |
134 | #elif defined(_MSC_VER)
135 | #define ASMCODE1(a) _asm _emit (a)
136 | #define ASMCODE2(a, b) ASMCODE1(a) ASMCODE1(b)
137 | #define ASMCODE3(a, b, c) ASMCODE2(a, b) ASMCODE1(c)
138 | #define ASMCODE4(a, b, c, d) ASMCODE3(a, b, c) ASMCODE1(d)
139 | #define ASMCODE5(a, b, c, d, e) ASMCODE4(a, b, c, d) ASMCODE1(e)
140 | #define ASMCODEW(n) ASMCODE2(((n) AND 0xff), ((n) / 0x100))
141 | #define ASMCODED(n) ASMCODEW(n) ASMCODEW((n) / 0x10000)
142 | #define ASMALIGN(n) ALIGN n
143 | #define __ALIGNC__ ASMALIGN(8)
144 | #define __INLINEMSC__
145 | #define ASM_BEGIN
146 | #define ASM_ENDUP
147 |
148 | #elif (defined(__BORLANDC__) || defined(__WATCOMC__))
149 | #define ASMCODE1(a) DB a;
150 | #define ASMCODE2(a, b) DB a, b;
151 | #define ASMCODE3(a, b, c) DB a, b, c;
152 | #define ASMCODE4(a, b, c, d) DB a, b, c, d;
153 | #define ASMCODE5(a, b, c, d, e) DB a, b, c, d, e;
154 | #define ASMCODEW(n) DW n;
155 | #define ASMCODED(n) DD n;
156 | #define ASMALIGN(n) ALIGN n
157 | #pragma warn -8002
158 | #pragma warn -8004
159 | #pragma warn -8008
160 | #pragma warn -8012
161 | #pragma warn -8027
162 | #pragma warn -8057
163 | #pragma warn -8066
164 | #define __ALIGNC__ ASMALIGN(4)
165 | #define __INLINEMSC__
166 | //#ifdef __WATCOMC__
167 | #undef __ALIGNC__
168 | #define __ALIGNC__
169 | //#endif
170 | #define ASM_BEGIN
171 | #define ASM_ENDUP
172 | #endif
173 | #endif
174 |
175 |
176 | #ifndef ASM_MMPREFETCH
177 | #define ASM_MMPREFETCH
178 | //---------------------------------------------------------------------
179 | // cache instructions operation code generation - SSE only
180 | //---------------------------------------------------------------------
181 | #define mm_prefetch_esi ASMCODE3(0x0f, 0x18, 0x06)
182 | #define mm_prefetch_edi ASMCODE3(0x0f, 0x18, 0x07)
183 | #define mm_sfence ASMCODE3(0x0f, 0xae, 0xf8)
184 | #endif
185 |
186 |
187 | //---------------------------------------------------------------------
188 | // transform instructions operation code generation - SSE only
189 | //---------------------------------------------------------------------
190 | #define mm_maskmovq(MMA, MMB) ASMCODE3(0x0f, 0xf7, 0xc0 | ((MMA)<<3)|(MMB) )
191 | #define mm_maskmovq_0_2 ASMCODE3(0x0f, 0xf7, 0xC2)
192 | #define mm_maskmovq_1_3 ASMCODE3(0x0f, 0xf7, 0xCB)
193 |
194 |
195 | #ifndef ASM_MMPREFETCHX
196 | #define ASM_MMPREFETCHX
197 | //---------------------------------------------------------------------
198 | // cache instructions extended operation code generation - SSE only
199 | //---------------------------------------------------------------------
200 | #define mm_prefetch_esi_n(n) ASMCODE3(0x0f, 0x18, 0x86) ASMCODED(n)
201 | #define mm_prefetch_edi_n(n) ASMCODE3(0x0f, 0x18, 0x87) ASMCODED(n)
202 | #define mm_prefetch_esi_8cx_n(n) ASMCODE4(0x0f,0x18,0x84,0xce) ASMCODED(n)
203 | #define mm_prefetch_esi_8dx ASMCODE4(0x0f, 0x18, 0x04, 0xd6)
204 | #define mm_prefetch_edi_8dx ASMCODE4(0x0f, 0x18, 0x04, 0xd7)
205 | #ifdef __WATCOMC__
206 | #undef mm_prefetch_esi_n
207 | #undef mm_prefetch_edi_n
208 | #undef mm_prefetch_esi_8cx_n
209 | #define mm_prefetch_esi_n(n) DD 0x86180f90, n
210 | #define mm_prefetch_edi_n(n) DD 0x86180f90, n
211 | #define mm_prefetch_esi_8cx_n(n) DD 0xCE84180f, n
212 | #endif
213 | #endif
214 |
215 | //---------------------------------------------------------------------
216 | // data instructions operation code generation - SSE only
217 | //---------------------------------------------------------------------
218 | #define mm_movntq_edi_0_m0 ASMCODE3(0x0f, 0xe7, 0x07)
219 | #define mm_movntq_edi_8_m1 ASMCODE4(0x0f, 0xe7, 0x4f, 0x08)
220 | #define mm_movntq_edi_16_m2 ASMCODE4(0x0f, 0xe7, 0x57, 0x10)
221 | #define mm_movntq_edi_24_m3 ASMCODE4(0x0f, 0xe7, 0x5f, 0x18)
222 | #define mm_movntq_edi_32_m4 ASMCODE4(0x0f, 0xe7, 0x67, 0x20)
223 | #define mm_movntq_edi_40_m5 ASMCODE4(0x0f, 0xe7, 0x6f, 0x28)
224 | #define mm_movntq_edi_48_m6 ASMCODE4(0x0f, 0xe7, 0x77, 0x30)
225 | #define mm_movntq_edi_56_m7 ASMCODE4(0x0f, 0xe7, 0x7f, 0x38)
226 |
227 |
228 | //---------------------------------------------------------------------
229 | // data instructions operation code generation - SSE only
230 | //---------------------------------------------------------------------
231 | #define mm_movntq_edi_8cx_0_m0 ASMCODE4(0x0f, 0xe7, 0x04, 0xcf)
232 | #define mm_movntq_edi_8cx_8_m1 ASMCODE5(0x0f, 0xe7, 0x4c, 0xcf, 0x08)
233 | #define mm_movntq_edi_8cx_16_m2 ASMCODE5(0x0f, 0xe7, 0x54, 0xcf, 0x10)
234 | #define mm_movntq_edi_8cx_24_m3 ASMCODE5(0x0f, 0xe7, 0x5c, 0xcf, 0x18)
235 | #define mm_movntq_edi_8cx_32_m4 ASMCODE5(0x0f, 0xe7, 0x64, 0xcf, 0x20)
236 | #define mm_movntq_edi_8cx_40_m5 ASMCODE5(0x0f, 0xe7, 0x6c, 0xcf, 0x28)
237 | #define mm_movntq_edi_8cx_48_m6 ASMCODE5(0x0f, 0xe7, 0x74, 0xcf, 0x30)
238 | #define mm_movntq_edi_8cx_56_m7 ASMCODE5(0x0f, 0xe7, 0x7c, 0xcf, 0x38)
239 |
240 |
241 | #define _MMX_FEATURE_BIT 0x00800000
242 | #define _SSE_FEATURE_BIT 0x02000000
243 | #define _SSE2_FEATURE_BIT 0x04000000
244 | #define _3DNOW_FEATURE_BIT 0x80000000
245 |
246 | #ifdef __cplusplus
247 | extern "C" {
248 | #endif
249 |
250 | //---------------------------------------------------------------------
251 | // X86 FEATURE DEFINITION
252 | //---------------------------------------------------------------------
253 | #define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */
254 | #define X86_FEATURE_VME (0*32+ 1) /* Virtual Mode Extensions */
255 | #define X86_FEATURE_DE (0*32+ 2) /* Debugging Extensions */
256 | #define X86_FEATURE_TSC (0*32+ 4) /* Time Stamp Counter */
257 | #define X86_FEATURE_MSR (0*32+ 5) /* Model-Specific Registers */
258 | #define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */
259 | #define X86_FEATURE_MCE (0*32+ 7) /* Machine Check Architecture */
260 | #define X86_FEATURE_CX8 (0*32+ 8) /* CMPXCHG8 instruction */
261 | #define X86_FEATURE_MCA (0*32+14) /* Machine Check Architecture */
262 | #define X86_FEATURE_CMOV (0*32+15) /* CMOV (FCMOVCC/FCOMI too if FPU) */
263 | #define X86_FEATURE_PAT (0*32+16) /* Page Attribute Table */
264 | #define X86_FEATURE_PSE36 (0*32+17) /* 36-bit PSEs */
265 | #define X86_FEATURE_CLFLSH (0*32+19) /* Supports the CLFLUSH instruction */
266 | #define X86_FEATURE_MMX (0*32+23) /* Multimedia Extensions */
267 | #define X86_FEATURE_XMM (0*32+25) /* Streaming SIMD Extensions */
268 | #define X86_FEATURE_XMM2 (0*32+26) /* Streaming SIMD Extensions-2 */
269 | #define X86_FEATURE_SELFSNOOP (0*32+27) /* CPU self snoop */
270 | #define X86_FEATURE_HT (0*32+28) /* Hyper-Threading */
271 | #define X86_FEATURE_ACC (0*32+29) /* Automatic clock control */
272 | #define X86_FEATURE_IA64 (0*32+30) /* IA-64 processor */
273 |
274 | #define X86_FEATURE_MP (1*32+19) /* MP Capable. */
275 | #define X86_FEATURE_NX (1*32+20) /* Execute Disable */
276 | #define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */
277 | #define X86_FEATURE_LM (1*32+29) /* Long Mode (x86-64) */
278 | #define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */
279 | #define X86_FEATURE_3DNOW (1*32+31) /* 3DNow! */
280 |
281 | #define X86_FEATURE_CXMMX (3*32+ 0) /* Cyrix MMX extensions */
282 | #define X86_FEATURE_K6_MTRR (3*32+ 1) /* AMD K6 nonstandard MTRRs */
283 | #define X86_FEATURE_CYRIX_ARR (3*32+ 2) /* Cyrix ARRs (= MTRRs) */
284 | #define X86_FEATURE_CENTAUR_MCR (3*32+ 3) /* Centaur MCRs (= MTRRs) */
285 | #define X86_FEATURE_K8 (3*32+ 4) /* Opteron, Athlon64 */
286 | #define X86_FEATURE_K7 (3*32+ 5) /* Athlon */
287 | #define X86_FEATURE_P3 (3*32+ 6) /* P3 */
288 | #define X86_FEATURE_P4 (3*32+ 7) /* P4 */
289 | #define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */
290 | #define X86_FEATURE_MWAIT (4*32+ 3) /* Monitor/Mwait support */
291 |
292 | #define X86_VENDOR_INTEL 0
293 | #define X86_VENDOR_CYRIX 1
294 | #define X86_VENDOR_AMD 2
295 | #define X86_VENDOR_UMC 3
296 | #define X86_VENDOR_NEXGEN 4
297 | #define X86_VENDOR_CENTAUR 5
298 | #define X86_VENDOR_RISE 6
299 | #define X86_VENDOR_TRANSMETA 7
300 | #define X86_VENDOR_NSC 8
301 | #define X86_VENDOR_NUM 9
302 | #define X86_VENDOR_SIS 10
303 | #define X86_VENDOR_UNKNOWN 0xff
304 |
305 |
306 | //---------------------------------------------------------------------
307 | // cpu global information
308 | //---------------------------------------------------------------------
309 | extern unsigned int _cpu_feature[];
310 | extern unsigned int _cpu_cachesize;
311 | extern int _cpu_level;
312 | extern int _cpu_device;
313 | extern int _cpu_vendor;
314 | extern char _cpu_vendor_name[];
315 | extern int _cpu_cache_l1i;
316 | extern int _cpu_cache_l1d;
317 | extern int _cpu_cache_l2;
318 |
319 | #define _TEST_BIT(p, x) (((unsigned int*)(p))[(x) >> 5] & (1 << ((x) & 31)))
320 | #define X86_FEATURE(x) _TEST_BIT(_cpu_feature, x)
321 |
322 | #ifndef IMASK32
323 | #define IMASK32 unsigned long
324 | #endif
325 |
326 | #ifndef ISRCPTR
327 | #define ISRCPTR const char *
328 | #endif
329 |
330 | #ifdef __amd64__
331 | typedef unsigned int IDWORD;
332 | typedef unsigned long IQWORD;
333 | #else
334 | typedef unsigned long IDWORD;
335 | #if defined(_MSC_VER) || defined(__BORLANDC__)
336 | typedef unsigned __int64 IQWORD;
337 | #else
338 | typedef unsigned long long IQWORD;
339 | #endif
340 | #endif
341 |
342 | #ifndef __IULONG_DEFINED
343 | #define __IULONG_DEFINED
344 | typedef ptrdiff_t ilong;
345 | typedef size_t iulong;
346 | #endif
347 |
348 | void _x86_cpuid(int op, int *eax, int *ebx, int *ecx, int *edx);
349 | void _x86_detect(void);
350 |
351 | void _x86_choose_blitter(void);
352 |
353 | int iblit_386(char*, long, const char*, long, int, int, int, long);
354 | int iblit_mmx(char*, long, const char*, long, int, int, int, long);
355 | int iblit_sse(char*, long, const char*, long, int, int, int, long);
356 | int iblit_mix(char*, long, const char*, long, int, int, int, long);
357 |
358 | int iblit_mask_mmx(char*, long, ISRCPTR, long, int, int, int, long, IMASK32);
359 | int iblit_mask_sse(char*, long, ISRCPTR, long, int, int, int, long, IMASK32);
360 | int iblit_mask_mix(char*, long, ISRCPTR, long, int, int, int, long, IMASK32);
361 |
362 |
363 | #ifdef __cplusplus
364 | }
365 | #endif
366 |
367 |
368 |
369 | //=====================================================================
370 | // MMX INLINE INSTRUCTIONS
371 | //=====================================================================
372 | #if defined(__GNUC__)
373 | #define immx_op(op) \
374 | __asm__ __volatile__ (#op "" : : : "memory")
375 | #define immx_op_r_r(op, regd, regs) \
376 | __asm__ __volatile__ (#op " %%" #regs ", %%" #regd "" : : : "memory")
377 | #define immx_op_r_i(op, regd, imm) \
378 | __asm__ __volatile__ (#op " %0, %%" #regd : : "i"(imm) : "memory")
379 | #define immx_op_r_m(op, regd, mem) \
380 | __asm__ __volatile__ (#op " %0, %%" #regd : : "m"(*(mem)) : "memory")
381 | #define immx_op_m_r(op, mem, regs) \
382 | __asm__ __volatile__ (#op " %%" #regs ", %0" : "=X"(*(mem)) : : "memory")
383 | #define immx_op_r_m32(op, regd, mem32) \
384 | immx_op_r_m(op, regd, mem32)
385 | #define immx_op_m32_r(op, mem32, regs) \
386 | immx_op_m_r(op, mem32, regs)
387 | #define immx_op_r_v(op, regd, vars) \
388 | immx_op_r_m(op, regd, (&(vars)))
389 | #define immx_op_v_r(op, vard, regs) \
390 | immx_op_m_r(op, (&(vard)), regs)
391 | typedef unsigned long long immx_uint64;
392 | typedef unsigned int immx_uint32;
393 | typedef long long immx_int64;
394 | typedef int immx_int32;
395 | #define immx_const_uint64(__imm__) (__imm__ ## ULL)
396 | #define immx_const_int64(__imm__) (__imm__ ## LL)
397 | #elif defined(_MSC_VER) || defined(__BORLANDC__)
398 | #define immx_op(op) \
399 | _asm { op }
400 | #define immx_op_r_r(op, regd, regs) \
401 | _asm { op regd, regs }
402 | #define immx_op_r_i(op, regd, imm) \
403 | _asm { op regd, imm }
404 | #define immx_op_r_m(op, regd, mem) \
405 | { register __int64 var = *(__int64*)(mem); _asm { op regd, var } }
406 | #define immx_op_m_r(op, mem, regs) \
407 | { register __int64 var; _asm { op var, regs }; *(__int64*)(mem) = var; }
408 | #define immx_op_r_m32(op, regd, mem32) \
409 | { register int var = *(int*)(mem32); _asm { op regd, var } }
410 | #define immx_op_m32_r(op, mem32, regs) \
411 | { register int var; _asm { op var, regs }; *(int*)(mem32) = var; }
412 | #define immx_op_r_v(op, regd, vars) \
413 | _asm { op regd, vars }
414 | #define immx_op_v_r(op, vard, regs) \
415 | _asm { op vard, regs }
416 | typedef unsigned __int64 immx_uint64;
417 | typedef unsigned int immx_uint32;
418 | typedef __int64 immx_int64;
419 | typedef int immx_int32;
420 | #define immx_const_uint64(__imm__) (__imm__ ## UI64)
421 | #define immx_const_int64(__imm__) (__imm__ ## I64)
422 | #endif
423 |
424 |
425 |
426 | //---------------------------------------------------------------------
427 | // MMX Instruction Tracing
428 | //---------------------------------------------------------------------
429 | #ifdef immx_op
430 |
431 | typedef union {
432 | immx_uint64 uq;
433 | immx_int64 q;
434 | immx_uint32 ud[2];
435 | immx_int32 d[2];
436 | unsigned short uw[4];
437 | short w[4];
438 | unsigned char ub[8];
439 | char b[8];
440 | float s[2];
441 | } immx_t;
442 |
443 | #define immx_op_trace(op) { \
444 | printf(#op "\n"); \
445 | immx_op(op); \
446 | }
447 |
448 | #define immx_op_m_m(op, memd, mems) { \
449 | immx_op_r_m(movq, mm0, memd); \
450 | immx_op_r_m(op, mm0, mems); \
451 | immx_op_m_r(movq, memd, mm0); \
452 | }
453 |
454 | #define immx_op_m32_m32(op, memd, mems) { \
455 | immx_op_r_m32(movd, mm0, memd); \
456 | immx_op_r_m32(movd, mm1, mems); \
457 | immx_op_r_r(op, mm0, mm1); \
458 | immx_op_m_r(movd, memd, mm0); \
459 | }
460 |
461 | #define immx_op_trace_r_r(op, regd, regs) { \
462 | immx_t mmx_trace; \
463 | immx_op_m_r(movq, &mmx_trace, regd); \
464 | printf(#op "_r_r(" #regd "=0x%08x%08x, ", \
465 | mmx_trace.d[1], mmx_trace.d[0]); \
466 | immx_op_m_r(movq, &mmx_trace, regs); \
467 | printf(#regs "=0x%08x%08x) => ", \
468 | mmx_trace.d[1], mmx_trace.d[0]); \
469 | immx_op_r_r(op, regd, regs); \
470 | immx_op_m_r(movq, &mmx_trace, regd); \
471 | printf(#regd "=0x%08x%08x\n", \
472 | mmx_trace.d[1], mmx_trace.d[0]); \
473 | }
474 |
475 | #define immx_op_trace_r_i(op, regd, imm) { \
476 | immx_t mmx_trace; \
477 | immx_op_m_r(movq, &mmx_trace, regd); \
478 | printf(#op "_r_i(" #regd "=0x%08x%08x, ", \
479 | mmx_trace.d[1], mmx_trace.d[0]); \
480 | mmx_trace.uq = (imm); \
481 | printf(#imm "=0x%08x%08x) => ", \
482 | mmx_trace.d[1], mmx_trace.d[0]); \
483 | immx_op_r_i(op, regd, imm); \
484 | immx_op_m_r(movq, &mmx_trace, regd); \
485 | printf(#regd "=0x%08x%08x\n", \
486 | mmx_trace.d[1], mmx_trace.d[0]); \
487 | }
488 |
489 | #define immx_op_trace_r_m(op, regd, mem) { \
490 | immx_t mmx_trace; \
491 | immx_op_m_r(movq, &mmx_trace, regd); \
492 | printf(#op "_r_m(" #regd "=0x%08x%08x, ", \
493 | mmx_trace.d[1], mmx_trace.d[0]); \
494 | mmx_trace.uq = *(immx_int64*)(mem); \
495 | printf(#mem "=0x%08x%08x) => ", \
496 | mmx_trace.d[1], mmx_trace.d[0]); \
497 | immx_op_r_m(op, regd, mem); \
498 | immx_op_m_r(movq, &mmx_trace, regd); \
499 | printf(#regd "=0x%08x%08x\n", \
500 | mmx_trace.d[1], mmx_trace.d[0]); \
501 | }
502 |
503 | #define immx_op_trace_m_r(op, mem, regs) { \
504 | immx_t mmx_trace; \
505 | mmx_trace.uq = *(immx_int64*)(mem); \
506 | printf(#op "_m_r(" #mem "=0x%08x%08x, ", \
507 | mmx_trace.d[1], mmx_trace.d[0]); \
508 | immx_op_m_r(movq, &mmx_trace, regs); \
509 | printf(#regs "=0x%08x%08x) => ", \
510 | mmx_trace.d[1], mmx_trace.d[0]); \
511 | immx_op_m_r(op, mem, regs); \
512 | mmx_trace.uq = *(immx_int64*)(mem); \
513 | printf(#mem "=0x%08x%08x\n", \
514 | mmx_trace.d[1], mmx_trace.d[0]); \
515 | }
516 |
517 | #define immx_op_trace_r_m32(op, regd, mem) { \
518 | immx_t mmx_trace; \
519 | immx_op_m_r(movq, &mmx_trace, regd); \
520 | printf(#op "_r_m32(" #regd "=0x%08x%08x, ", \
521 | mmx_trace.d[1], mmx_trace.d[0]); \
522 | mmx_trace.d[0] = *(immx_int32*)(mem); \
523 | mmx_trace.d[1] = 0; \
524 | printf(#mem "=0x%08x%08x) => ", \
525 | mmx_trace.d[1], mmx_trace.d[0]); \
526 | immx_op_r_m32(op, regd, mem); \
527 | immx_op_m_r(movq, &mmx_trace, regd); \
528 | printf(#regd "=0x%08x%08x\n", \
529 | mmx_trace.d[1], mmx_trace.d[0]); \
530 | }
531 |
532 | #define immx_op_trace_m32_r(op, mem, regs) { \
533 | immx_t mmx_trace; \
534 | mmx_trace.d[0] = *(immx_int32*)(mem); \
535 | mmx_trace.d[1] = 0; \
536 | printf(#op "_m32_r(" #mem "=0x%08x%08x, ", \
537 | mmx_trace.d[1], mmx_trace.d[0]); \
538 | immx_op_m_r(movq, &mmx_trace, regs); \
539 | printf(#regs "=0x%08x%08x) => ", \
540 | mmx_trace.d[1], mmx_trace.d[0]); \
541 | immx_op_m32_r(op, mem, regs); \
542 | mmx_trace.d[0] = *(immx_int32*)(mem); \
543 | mmx_trace.d[1] = 0; \
544 | printf(#mem "=0x%08x%08x\n", \
545 | mmx_trace.d[1], mmx_trace.d[0]); \
546 | }
547 |
548 | #define immx_op_trace_m_m(op, memd, mems) { \
549 | immx_t mmx_trace1, mmx_trace2; \
550 | immx_op_r_m(movq, mm0, memd); \
551 | immx_op_r_m(movq, mm1, mems); \
552 | immx_op_m_r(movq, &mmx_trace1, mm0); \
553 | immx_op_m_r(movq, &mmx_trace2, mm1); \
554 | printf(#op "_m_m(" #memd "=0x%08x%08x, ", \
555 | mmx_trace1.d[1], mmx_trace1.d[0]); \
556 | printf(#mems "=0x%08x%08x) => ", \
557 | mmx_trace2.d[1], mmx_trace2.d[0]); \
558 | immx_op_m_m(op, memd, mems); \
559 | immx_op_r_m(movq, mm0, memd); \
560 | immx_op_m_r(movq, &mmx_trace1, mm0); \
561 | printf(#memd "=0x%08x%08x\n", \
562 | mmx_trace1.d[1], mmx_trace1.d[0]); \
563 | }
564 |
565 | #define immx_op_trace_m32_m32(op, memd, mems) { \
566 | immx_t mmx_trace1, mmx_trace2; \
567 | immx_op_r_m32(movd, mm0, memd); \
568 | immx_op_r_m32(movd, mm1, mems); \
569 | immx_op_m_r(movq, immx_addr(mmx_trace1), mm0); \
570 | immx_op_m_r(movq, immx_addr(mmx_trace2), mm1); \
571 | printf(#op "_m_m(" #memd "=0x%08x, ", mmx_trace1.d[0]); \
572 | printf(#mems "=0x%08x) => ", mmx_trace2.d[0]); \
573 | immx_op_m_m(op, memd, mems); \
574 | immx_op_r_m32(movd, mm0, memd); \
575 | immx_op_m_r(movq, immx_addr(mmx_trace1), mm0); \
576 | printf(#memd "=0x%08x\n", mmx_trace1.d[0]); \
577 | }
578 |
579 | #define immx_op_trace_r_v(op, regd, vars) { \
580 | immx_t mmx_trace; \
581 | immx_op_m_r(movq, &mmx_trace, regd); \
582 | printf(#op "_r_v(" #regd "=0x%08x%08x, ", \
583 | mmx_trace.d[1], mmx_trace.d[0]); \
584 | mmx_trace.uq = (immx_int64)(vars); \
585 | printf(#vars "=0x%08x%08x) => ", \
586 | mmx_trace.d[1], mmx_trace.d[0]); \
587 | immx_op_r_v(op, regd, vars); \
588 | immx_op_m_r(movq, &mmx_trace, regd); \
589 | printf(#regd "=0x%08x%08x\n", \
590 | mmx_trace.d[1], mmx_trace.d[0]); \
591 | }
592 |
593 | #define immx_op_trace_v_r(op, vard, regs) { \
594 | immx_t mmx_trace; \
595 | mmx_trace.uq = (immx_int64)(vard); \
596 | printf(#op "_v_r(" #vard "=0x%08x%08x, ", \
597 | mmx_trace.d[1], mmx_trace.d[0]); \
598 | immx_op_m_r(movq, &mmx_trace, regs); \
599 | printf(#regs "=0x%08x%08x) => ", \
600 | mmx_trace.d[1], mmx_trace.d[0]); \
601 | immx_op_v_r(op, vard, regs); \
602 | mmx_trace.uq = (immx_int64)(vard); \
603 | printf(#vard "=0x%08x%08x\n", \
604 | mmx_trace.d[1], mmx_trace.d[0]); \
605 | }
606 |
607 | #define immx_trace_print_reg(regs) { \
608 | immx_t mmx_trace; \
609 | immx_op_m_r(movq, immx_addr(mmx_trace), regs); \
610 | printf(#regs "=0x%08x%08x\n", \
611 | mmx_trace.d[1], mmx_trace.d[0]); \
612 | }
613 |
614 | #endif
615 |
616 |
617 | #ifndef IMMX_TRACE
618 | #define immx_inst(op) immx_op(op)
619 | #define immx_inst_r_r(op, regd, regs) immx_op_r_r(op, regd, regs)
620 | #define immx_inst_r_i(op, regd, imm) immx_op_r_i(op, regd, imm)
621 | #define immx_inst_r_m(op, regd, mem) immx_op_r_m(op, regd, mem)
622 | #define immx_inst_m_r(op, mem, regs) immx_op_m_r(op, mem, regs)
623 | #define immx_inst_r_m32(op, regd, mem) immx_op_r_m32(op, regd, mem)
624 | #define immx_inst_m32_r(op, mem, regs) immx_op_m32_r(op, mem, regs)
625 | #define immx_inst_r_v(op, regd, vars) immx_op_r_v(op, regd, vars)
626 | #define immx_inst_v_r(op, vard, regs) immx_op_v_r(op, vard, regs)
627 | #define immx_inst_m_m(op, memd, mems) immx_op_m_m(op, memd, mems)
628 | #define immx_inst_m32_m32(op, m1, m2) immx_op_m32_m32(op, m1, m2)
629 | #define immx_trace_reg(reg)
630 | #else
631 | #define immx_inst(op) immx_op_trace(op)
632 | #define immx_inst_r_r(op, regd, regs) immx_op_trace_r_r(op, regd, regs)
633 | #define immx_inst_r_i(op, regd, imm) immx_op_trace_r_i(op, regd, imm)
634 | #define immx_inst_r_m(op, regd, mem) immx_op_trace_r_m(op, regd, mem)
635 | #define immx_inst_m_r(op, mem, regs) immx_op_trace_m_r(op, mem, regs)
636 | #define immx_inst_r_m32(op, regd, mem) immx_op_trace_r_m32(op, regd, mem)
637 | #define immx_inst_m32_r(op, mem, regs) immx_op_trace_m32_r(op, mem, regs)
638 | #define immx_inst_r_v(op, regd, vars) immx_op_trace_r_v(op, regd, vars)
639 | #define immx_inst_v_r(op, vard, regs) immx_op_trace_v_r(op, vard, regs)
640 | #define immx_inst_m_m(op, memd, mems) immx_op_trace_m_m(op, memd, mems)
641 | #define immx_inst_m32_m32(op, m1, m2) immx_op_trace_m32_m32(op, m1, m2)
642 | #define immx_trace_reg(reg) immx_trace_print_reg(reg)
643 | #endif
644 |
645 |
646 | //---------------------------------------------------------------------
647 | // MMX instructions (generated by python)
648 | //---------------------------------------------------------------------
649 | #define movq_r_r(regd, regs) immx_inst_r_r(movq, regd, regs)
650 | #define movq_r_m(regd, mem) immx_inst_r_m(movq, regd, mem)
651 | #define movq_m_r(mem, regs) immx_inst_m_r(movq, mem, regs)
652 | #define movq_m_m(memd, mems) immx_inst_m_m(movq, memd, mems)
653 | #define movq_r_v(regd, vars) immx_inst_r_v(movq, regd, vars)
654 | #define movq_v_r(vard, regs) immx_inst_v_r(movq, vard, regs)
655 |
656 | #define movd_r_r(regd, regs) immx_inst_r_r(movd, regd, regs)
657 | #define movd_r_m(regd, mem) immx_inst_r_m32(movd, regd, mem)
658 | #define movd_m_r(mem, regs) immx_inst_m32_r(movd, mem, regs)
659 | #define movd_m_m(memd, mems) immx_inst_m_m(movd, memd, mems)
660 | #define movd_r_v(regd, vars) immx_inst_r_v(movd, regd, vars)
661 | #define movd_v_r(vard, regs) immx_inst_v_r(movd, vard, regs)
662 |
663 | #define paddd_r_m(regd, mem) immx_inst_r_m(paddd, regd, mem)
664 | #define paddd_r_r(regd, regs) immx_inst_r_r(paddd, regd, regs)
665 | #define paddd_r_v(regd, vars) immx_inst_r_v(paddd, regd, vars)
666 | #define paddw_r_m(regd, mem) immx_inst_r_m(paddw, regd, mem)
667 | #define paddw_r_r(regd, regs) immx_inst_r_r(paddw, regd, regs)
668 | #define paddw_r_v(regd, vars) immx_inst_r_v(paddw, regd, vars)
669 | #define paddb_r_m(regd, mem) immx_inst_r_m(paddb, regd, mem)
670 | #define paddb_r_r(regd, regs) immx_inst_r_r(paddb, regd, regs)
671 | #define paddb_r_v(regd, vars) immx_inst_r_v(paddb, regd, vars)
672 |
673 | #define paddsw_r_m(regd, mem) immx_inst_r_m(paddsw, regd, mem)
674 | #define paddsw_r_r(regd, regs) immx_inst_r_r(paddsw, regd, regs)
675 | #define paddsw_r_v(regd, vars) immx_inst_r_v(paddsw, regd, vars)
676 | #define paddsb_r_m(regd, mem) immx_inst_r_m(paddsb, regd, mem)
677 | #define paddsb_r_r(regd, regs) immx_inst_r_r(paddsb, regd, regs)
678 | #define paddsb_r_v(regd, vars) immx_inst_r_v(paddsb, regd, vars)
679 |
680 | #define paddusw_r_m(regd, mem) immx_inst_r_m(paddusw, regd, mem)
681 | #define paddusw_r_r(regd, regs) immx_inst_r_r(paddusw, regd, regs)
682 | #define paddusw_r_v(regd, vars) immx_inst_r_v(paddusw, regd, vars)
683 | #define paddusb_r_m(regd, mem) immx_inst_r_m(paddusb, regd, mem)
684 | #define paddusb_r_r(regd, regs) immx_inst_r_r(paddusb, regd, regs)
685 | #define paddusb_r_v(regd, vars) immx_inst_r_v(paddusb, regd, vars)
686 |
687 | #define psubd_r_m(regd, mem) immx_inst_r_m(psubd, regd, mem)
688 | #define psubd_r_r(regd, regs) immx_inst_r_r(psubd, regd, regs)
689 | #define psubd_r_v(regd, vars) immx_inst_r_v(psubd, regd, vars)
690 | #define psubw_r_m(regd, mem) immx_inst_r_m(psubw, regd, mem)
691 | #define psubw_r_r(regd, regs) immx_inst_r_r(psubw, regd, regs)
692 | #define psubw_r_v(regd, vars) immx_inst_r_v(psubw, regd, vars)
693 | #define psubb_r_m(regd, mem) immx_inst_r_m(psubb, regd, mem)
694 | #define psubb_r_r(regd, regs) immx_inst_r_r(psubb, regd, regs)
695 | #define psubb_r_v(regd, vars) immx_inst_r_v(psubb, regd, vars)
696 |
697 | #define psubsw_r_m(regd, mem) immx_inst_r_m(psubsw, regd, mem)
698 | #define psubsw_r_r(regd, regs) immx_inst_r_r(psubsw, regd, regs)
699 | #define psubsw_r_v(regd, vars) immx_inst_r_v(psubsw, regd, vars)
700 | #define psubsb_r_m(regd, mem) immx_inst_r_m(psubsb, regd, mem)
701 | #define psubsb_r_r(regd, regs) immx_inst_r_r(psubsb, regd, regs)
702 | #define psubsb_r_v(regd, vars) immx_inst_r_v(psubsb, regd, vars)
703 |
704 | #define psubusw_r_m(regd, mem) immx_inst_r_m(psubusw, regd, mem)
705 | #define psubusw_r_r(regd, regs) immx_inst_r_r(psubusw, regd, regs)
706 | #define psubusw_r_v(regd, vars) immx_inst_r_v(psubusw, regd, vars)
707 | #define psubusb_r_m(regd, mem) immx_inst_r_m(psubusb, regd, mem)
708 | #define psubusb_r_r(regd, regs) immx_inst_r_r(psubusb, regd, regs)
709 | #define psubusb_r_v(regd, vars) immx_inst_r_v(psubusb, regd, vars)
710 |
711 | #define pmullw_r_m(regd, mem) immx_inst_r_m(pmullw, regd, mem)
712 | #define pmullw_r_r(regd, regs) immx_inst_r_r(pmullw, regd, regs)
713 | #define pmullw_r_v(regd, vars) immx_inst_r_v(pmullw, regd, vars)
714 |
715 | #define pmulhw_r_m(regd, mem) immx_inst_r_m(pmulhw, regd, mem)
716 | #define pmulhw_r_r(regd, regs) immx_inst_r_r(pmulhw, regd, regs)
717 | #define pmulhw_r_v(regd, vars) immx_inst_r_v(pmulhw, regd, vars)
718 |
719 | #define pmaddwd_r_m(regd, mem) immx_inst_r_m(pmaddwd, regd, mem)
720 | #define pmaddwd_r_r(regd, regs) immx_inst_r_r(pmaddwd, regd, regs)
721 | #define pmaddwd_r_v(regd, vars) immx_inst_r_v(pmaddwd, regd, vars)
722 |
723 | #define pand_r_m(regd, mem) immx_inst_r_m(pand, regd, mem)
724 | #define pand_r_r(regd, regs) immx_inst_r_r(pand, regd, regs)
725 | #define pand_r_v(regd, vars) immx_inst_r_v(pand, regd, vars)
726 |
727 | #define pandn_r_m(regd, mem) immx_inst_r_m(pandn, regd, mem)
728 | #define pandn_r_r(regd, regs) immx_inst_r_r(pandn, regd, regs)
729 | #define pandn_r_v(regd, vars) immx_inst_r_v(pandn, regd, vars)
730 |
731 | #define por_r_m(regd, mem) immx_inst_r_m(por, regd, mem)
732 | #define por_r_r(regd, regs) immx_inst_r_r(por, regd, regs)
733 | #define por_r_v(regd, vars) immx_inst_r_v(por, regd, vars)
734 |
735 | #define pxor_r_m(regd, mem) immx_inst_r_m(pxor, regd, mem)
736 | #define pxor_r_r(regd, regs) immx_inst_r_r(pxor, regd, regs)
737 | #define pxor_r_v(regd, vars) immx_inst_r_v(pxor, regd, vars)
738 |
739 | #define pcmpeqd_r_m(regd, mem) immx_inst_r_m(pcmpeqd, regd, mem)
740 | #define pcmpeqd_r_r(regd, regs) immx_inst_r_r(pcmpeqd, regd, regs)
741 | #define pcmpeqd_r_v(regd, vars) immx_inst_r_v(pcmpeqd, regd, vars)
742 | #define pcmpeqw_r_m(regd, mem) immx_inst_r_m(pcmpeqw, regd, mem)
743 | #define pcmpeqw_r_r(regd, regs) immx_inst_r_r(pcmpeqw, regd, regs)
744 | #define pcmpeqw_r_v(regd, vars) immx_inst_r_v(pcmpeqw, regd, vars)
745 | #define pcmpeqb_r_m(regd, mem) immx_inst_r_m(pcmpeqb, regd, mem)
746 | #define pcmpeqb_r_r(regd, regs) immx_inst_r_r(pcmpeqb, regd, regs)
747 | #define pcmpeqb_r_v(regd, vars) immx_inst_r_v(pcmpeqb, regd, vars)
748 |
749 | #define pcmpgtd_r_m(regd, mem) immx_inst_r_m(pcmpgtd, regd, mem)
750 | #define pcmpgtd_r_r(regd, regs) immx_inst_r_r(pcmpgtd, regd, regs)
751 | #define pcmpgtd_r_v(regd, vars) immx_inst_r_v(pcmpgtd, regd, vars)
752 | #define pcmpgtw_r_m(regd, mem) immx_inst_r_m(pcmpgtw, regd, mem)
753 | #define pcmpgtw_r_r(regd, regs) immx_inst_r_r(pcmpgtw, regd, regs)
754 | #define pcmpgtw_r_v(regd, vars) immx_inst_r_v(pcmpgtw, regd, vars)
755 | #define pcmpgtb_r_m(regd, mem) immx_inst_r_m(pcmpgtb, regd, mem)
756 | #define pcmpgtb_r_r(regd, regs) immx_inst_r_r(pcmpgtb, regd, regs)
757 | #define pcmpgtb_r_v(regd, vars) immx_inst_r_v(pcmpgtb, regd, vars)
758 |
759 | #define psllq_r_i(regd, imm) immx_inst_r_i(psllq, regd, imm)
760 | #define psllq_r_m(regd, mem) immx_inst_r_m(psllq, regd, mem)
761 | #define psllq_r_r(regd, regs) immx_inst_r_r(psllq, regd, regs)
762 | #define psllq_r_v(regd, vars) immx_inst_r_v(psllq, regd, vars)
763 | #define pslld_r_i(regd, imm) immx_inst_r_i(pslld, regd, imm)
764 | #define pslld_r_m(regd, mem) immx_inst_r_m(pslld, regd, mem)
765 | #define pslld_r_r(regd, regs) immx_inst_r_r(pslld, regd, regs)
766 | #define pslld_r_v(regd, vars) immx_inst_r_v(pslld, regd, vars)
767 | #define psllw_r_i(regd, imm) immx_inst_r_i(psllw, regd, imm)
768 | #define psllw_r_m(regd, mem) immx_inst_r_m(psllw, regd, mem)
769 | #define psllw_r_r(regd, regs) immx_inst_r_r(psllw, regd, regs)
770 | #define psllw_r_v(regd, vars) immx_inst_r_v(psllw, regd, vars)
771 |
772 | #define psrlq_r_i(regd, imm) immx_inst_r_i(psrlq, regd, imm)
773 | #define psrlq_r_m(regd, mem) immx_inst_r_m(psrlq, regd, mem)
774 | #define psrlq_r_r(regd, regs) immx_inst_r_r(psrlq, regd, regs)
775 | #define psrlq_r_v(regd, vars) immx_inst_r_v(psrlq, regd, vars)
776 | #define psrld_r_i(regd, imm) immx_inst_r_i(psrld, regd, imm)
777 | #define psrld_r_m(regd, mem) immx_inst_r_m(psrld, regd, mem)
778 | #define psrld_r_r(regd, regs) immx_inst_r_r(psrld, regd, regs)
779 | #define psrld_r_v(regd, vars) immx_inst_r_v(psrld, regd, vars)
780 | #define psrlw_r_i(regd, imm) immx_inst_r_i(psrlw, regd, imm)
781 | #define psrlw_r_m(regd, mem) immx_inst_r_m(psrlw, regd, mem)
782 | #define psrlw_r_r(regd, regs) immx_inst_r_r(psrlw, regd, regs)
783 | #define psrlw_r_v(regd, vars) immx_inst_r_v(psrlw, regd, vars)
784 |
785 | #define psrad_r_i(regd, imm) immx_inst_r_i(psrad, regd, imm)
786 | #define psrad_r_m(regd, mem) immx_inst_r_m(psrad, regd, mem)
787 | #define psrad_r_r(regd, regs) immx_inst_r_r(psrad, regd, regs)
788 | #define psrad_r_v(regd, vars) immx_inst_r_v(psrad, regd, vars)
789 | #define psraw_r_i(regd, imm) immx_inst_r_i(psraw, regd, imm)
790 | #define psraw_r_m(regd, mem) immx_inst_r_m(psraw, regd, mem)
791 | #define psraw_r_r(regd, regs) immx_inst_r_r(psraw, regd, regs)
792 | #define psraw_r_v(regd, vars) immx_inst_r_v(psraw, regd, vars)
793 |
794 | #define packssdw_r_m(regd, mem) immx_inst_r_m(packssdw, regd, mem)
795 | #define packssdw_r_r(regd, regs) immx_inst_r_r(packssdw, regd, regs)
796 | #define packssdw_r_v(regd, vars) immx_inst_r_v(packssdw, regd, vars)
797 | #define packsswb_r_m(regd, mem) immx_inst_r_m(packsswb, regd, mem)
798 | #define packsswb_r_r(regd, regs) immx_inst_r_r(packsswb, regd, regs)
799 | #define packsswb_r_v(regd, vars) immx_inst_r_v(packsswb, regd, vars)
800 |
801 | #define packuswb_r_m(regd, mem) immx_inst_r_m(packuswb, regd, mem)
802 | #define packuswb_r_r(regd, regs) immx_inst_r_r(packuswb, regd, regs)
803 | #define packuswb_r_v(regd, vars) immx_inst_r_v(packuswb, regd, vars)
804 |
805 | #define punpckldq_r_m(regd, mem) immx_inst_r_m(punpckldq, regd, mem)
806 | #define punpckldq_r_r(regd, regs) immx_inst_r_r(punpckldq, regd, regs)
807 | #define punpckldq_r_v(regd, vars) immx_inst_r_v(punpckldq, regd, vars)
808 | #define punpcklwd_r_m(regd, mem) immx_inst_r_m(punpcklwd, regd, mem)
809 | #define punpcklwd_r_r(regd, regs) immx_inst_r_r(punpcklwd, regd, regs)
810 | #define punpcklwd_r_v(regd, vars) immx_inst_r_v(punpcklwd, regd, vars)
811 | #define punpcklbw_r_m(regd, mem) immx_inst_r_m(punpcklbw, regd, mem)
812 | #define punpcklbw_r_r(regd, regs) immx_inst_r_r(punpcklbw, regd, regs)
813 | #define punpcklbw_r_v(regd, vars) immx_inst_r_v(punpcklbw, regd, vars)
814 |
815 | #define punpckhdq_r_m(regd, mem) immx_inst_r_m(punpckhdq, regd, mem)
816 | #define punpckhdq_r_r(regd, regs) immx_inst_r_r(punpckhdq, regd, regs)
817 | #define punpckhdq_r_v(regd, vars) immx_inst_r_v(punpckhdq, regd, vars)
818 | #define punpckhwd_r_m(regd, mem) immx_inst_r_m(punpckhwd, regd, mem)
819 | #define punpckhwd_r_r(regd, regs) immx_inst_r_r(punpckhwd, regd, regs)
820 | #define punpckhwd_r_v(regd, vars) immx_inst_r_v(punpckhwd, regd, vars)
821 | #define punpckhbw_r_m(regd, mem) immx_inst_r_m(punpckhbw, regd, mem)
822 | #define punpckhbw_r_r(regd, regs) immx_inst_r_r(punpckhbw, regd, regs)
823 | #define punpckhbw_r_v(regd, vars) immx_inst_r_v(punpckhbw, regd, vars)
824 |
825 | #define immx_emms() immx_inst(emms)
826 |
827 |
828 | #if (defined(__i386__) || defined(__amd64__) || defined(_M_IA64))
829 | #if defined(immx_inst) && defined(__x86__)
830 | #define ASMMMX_ENABLE
831 | #define __asmmmx__
832 | #endif
833 | #endif
834 |
835 | #endif
836 |
837 | #endif
838 |
839 |
840 |
--------------------------------------------------------------------------------
/pixellib/ibmcols.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/ibmcols.c
--------------------------------------------------------------------------------
/pixellib/ibmcols.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/ibmcols.h
--------------------------------------------------------------------------------
/pixellib/ibmdata.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/ibmdata.c
--------------------------------------------------------------------------------
/pixellib/ibmdata.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/ibmdata.h
--------------------------------------------------------------------------------
/pixellib/ibmfont.c:
--------------------------------------------------------------------------------
1 | //=====================================================================
2 | //
3 | // ibmfont.c - builtin font operation
4 | //
5 | // NOTE:
6 | // for more information, please see the readme file
7 | //
8 | //=====================================================================
9 | #include "ibmfont.h"
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 |
19 |
20 | // builtin font
21 | static const unsigned char _ifont_asc16[4096] = {
22 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,126,129,165,129,129,189,153,129,129,126,
23 | 0,0,0,0,0,0,126,255,219,255,255,195,231,255,255,126,0,0,0,0,0,0,0,0,108,254,
24 | 254,254,254,124,56,16,0,0,0,0,0,0,0,0,16,56,124,254,124,56,16,0,0,0,0,0,0,
25 | 0,0,24,60,60,231,231,231,24,24,60,0,0,0,0,0,0,0,24,60,126,255,255,126,24,
26 | 24,60,0,0,0,0,0,0,0,0,0,0,24,60,60,24,0,0,0,0,0,0,255,255,255,255,255,255,
27 | 231,195,195,231,255,255,255,255,255,255,0,0,0,0,0,60,102,66,66,102,60,0,0,
28 | 0,0,0,255,255,255,255,255,195,153,189,189,153,195,255,255,255,255,255,0,0,
29 | 30,14,26,50,120,204,204,204,204,120,0,0,0,0,0,0,60,102,102,102,102,60,24,
30 | 126,24,24,0,0,0,0,0,0,63,51,63,48,48,48,48,112,240,224,0,0,0,0,0,0,127,99,
31 | 127,99,99,99,99,103,231,230,192,0,0,0,0,0,0,24,24,219,60,231,60,219,24,24,
32 | 0,0,0,0,0,128,192,224,240,248,254,248,240,224,192,128,0,0,0,0,0,2,6,14,30,
33 | 62,254,62,30,14,6,2,0,0,0,0,0,0,24,60,126,24,24,24,126,60,24,0,0,0,0,0,0,
34 | 0,102,102,102,102,102,102,102,0,102,102,0,0,0,0,0,0,127,219,219,219,123,27,
35 | 27,27,27,27,0,0,0,0,0,124,198,96,56,108,198,198,108,56,12,198,124,0,0,0,0,
36 | 0,0,0,0,0,0,0,254,254,254,254,0,0,0,0,0,0,24,60,126,24,24,24,126,60,24,126,
37 | 0,0,0,0,0,0,24,60,126,24,24,24,24,24,24,24,0,0,0,0,0,0,24,24,24,24,24,24,
38 | 24,126,60,24,0,0,0,0,0,0,0,0,0,24,12,254,12,24,0,0,0,0,0,0,0,0,0,0,0,48,96,
39 | 254,96,48,0,0,0,0,0,0,0,0,0,0,0,0,192,192,192,254,0,0,0,0,0,0,0,0,0,0,0,40,
40 | 108,254,108,40,0,0,0,0,0,0,0,0,0,0,16,56,56,124,124,254,254,0,0,0,0,0,0,0,
41 | 0,0,254,254,124,124,56,56,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
42 | 0,24,60,60,60,24,24,24,0,24,24,0,0,0,0,0,102,102,102,36,0,0,0,0,0,0,0,0,0,
43 | 0,0,0,0,0,108,108,254,108,108,108,254,108,108,0,0,0,0,24,24,124,198,194,192,
44 | 124,6,6,134,198,124,24,24,0,0,0,0,0,0,194,198,12,24,48,96,198,134,0,0,0,0,
45 | 0,0,56,108,108,56,118,220,204,204,204,118,0,0,0,0,0,48,48,48,96,0,0,0,0,0,
46 | 0,0,0,0,0,0,0,0,12,24,48,48,48,48,48,48,24,12,0,0,0,0,0,0,48,24,12,12,12,
47 | 12,12,12,24,48,0,0,0,0,0,0,0,0,0,102,60,255,60,102,0,0,0,0,0,0,0,0,0,0,0,
48 | 24,24,126,24,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,24,24,48,0,0,0,0,0,0,0,0,
49 | 0,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,24,0,0,0,0,0,0,0,0,2,6,12,
50 | 24,48,96,192,128,0,0,0,0,0,0,56,108,198,198,214,214,198,198,108,56,0,0,0,
51 | 0,0,0,24,56,120,24,24,24,24,24,24,126,0,0,0,0,0,0,124,198,6,12,24,48,96,192,
52 | 198,254,0,0,0,0,0,0,124,198,6,6,60,6,6,6,198,124,0,0,0,0,0,0,12,28,60,108,
53 | 204,254,12,12,12,30,0,0,0,0,0,0,254,192,192,192,252,6,6,6,198,124,0,0,0,0,
54 | 0,0,56,96,192,192,252,198,198,198,198,124,0,0,0,0,0,0,254,198,6,6,12,24,48,
55 | 48,48,48,0,0,0,0,0,0,124,198,198,198,124,198,198,198,198,124,0,0,0,0,0,0,
56 | 124,198,198,198,126,6,6,6,12,120,0,0,0,0,0,0,0,0,24,24,0,0,0,24,24,0,0,0,
57 | 0,0,0,0,0,0,24,24,0,0,0,24,24,48,0,0,0,0,0,0,0,6,12,24,48,96,48,24,12,6,0,
58 | 0,0,0,0,0,0,0,0,126,0,0,126,0,0,0,0,0,0,0,0,0,0,96,48,24,12,6,12,24,48,96,
59 | 0,0,0,0,0,0,124,198,198,12,24,24,24,0,24,24,0,0,0,0,0,0,0,124,198,198,222,
60 | 222,222,220,192,124,0,0,0,0,0,0,16,56,108,198,198,254,198,198,198,198,0,0,
61 | 0,0,0,0,252,102,102,102,124,102,102,102,102,252,0,0,0,0,0,0,60,102,194,192,
62 | 192,192,192,194,102,60,0,0,0,0,0,0,248,108,102,102,102,102,102,102,108,248,
63 | 0,0,0,0,0,0,254,102,98,104,120,104,96,98,102,254,0,0,0,0,0,0,254,102,98,104,
64 | 120,104,96,96,96,240,0,0,0,0,0,0,60,102,194,192,192,222,198,198,102,58,0,
65 | 0,0,0,0,0,198,198,198,198,254,198,198,198,198,198,0,0,0,0,0,0,60,24,24,24,
66 | 24,24,24,24,24,60,0,0,0,0,0,0,30,12,12,12,12,12,204,204,204,120,0,0,0,0,0,
67 | 0,230,102,102,108,120,120,108,102,102,230,0,0,0,0,0,0,240,96,96,96,96,96,
68 | 96,98,102,254,0,0,0,0,0,0,198,238,254,254,214,198,198,198,198,198,0,0,0,0,
69 | 0,0,198,230,246,254,222,206,198,198,198,198,0,0,0,0,0,0,124,198,198,198,198,
70 | 198,198,198,198,124,0,0,0,0,0,0,252,102,102,102,124,96,96,96,96,240,0,0,0,
71 | 0,0,0,124,198,198,198,198,198,198,214,222,124,12,14,0,0,0,0,252,102,102,102,
72 | 124,108,102,102,102,230,0,0,0,0,0,0,124,198,198,96,56,12,6,198,198,124,0,
73 | 0,0,0,0,0,126,126,90,24,24,24,24,24,24,60,0,0,0,0,0,0,198,198,198,198,198,
74 | 198,198,198,198,124,0,0,0,0,0,0,198,198,198,198,198,198,198,108,56,16,0,0,
75 | 0,0,0,0,198,198,198,198,214,214,214,254,238,108,0,0,0,0,0,0,198,198,108,124,
76 | 56,56,124,108,198,198,0,0,0,0,0,0,102,102,102,102,60,24,24,24,24,60,0,0,0,
77 | 0,0,0,254,198,134,12,24,48,96,194,198,254,0,0,0,0,0,0,60,48,48,48,48,48,48,
78 | 48,48,60,0,0,0,0,0,0,0,128,192,224,112,56,28,14,6,2,0,0,0,0,0,0,60,12,12,
79 | 12,12,12,12,12,12,60,0,0,0,0,16,56,108,198,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
80 | 0,0,0,0,0,0,0,0,0,0,255,0,0,48,48,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
81 | 120,12,124,204,204,204,118,0,0,0,0,0,0,224,96,96,120,108,102,102,102,102,
82 | 124,0,0,0,0,0,0,0,0,0,124,198,192,192,192,198,124,0,0,0,0,0,0,28,12,12,60,
83 | 108,204,204,204,204,118,0,0,0,0,0,0,0,0,0,124,198,254,192,192,198,124,0,0,
84 | 0,0,0,0,56,108,100,96,240,96,96,96,96,240,0,0,0,0,0,0,0,0,0,118,204,204,204,
85 | 204,204,124,12,204,120,0,0,0,224,96,96,108,118,102,102,102,102,230,0,0,0,
86 | 0,0,0,24,24,0,56,24,24,24,24,24,60,0,0,0,0,0,0,6,6,0,14,6,6,6,6,6,6,102,102,
87 | 60,0,0,0,224,96,96,102,108,120,120,108,102,230,0,0,0,0,0,0,56,24,24,24,24,
88 | 24,24,24,24,60,0,0,0,0,0,0,0,0,0,236,254,214,214,214,214,198,0,0,0,0,0,0,
89 | 0,0,0,220,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,124,198,198,198,198,198,
90 | 124,0,0,0,0,0,0,0,0,0,220,102,102,102,102,102,124,96,96,240,0,0,0,0,0,0,118,
91 | 204,204,204,204,204,124,12,12,30,0,0,0,0,0,0,220,118,102,96,96,96,240,0,0,
92 | 0,0,0,0,0,0,0,124,198,96,56,12,198,124,0,0,0,0,0,0,16,48,48,252,48,48,48,
93 | 48,54,28,0,0,0,0,0,0,0,0,0,204,204,204,204,204,204,118,0,0,0,0,0,0,0,0,0,
94 | 102,102,102,102,102,60,24,0,0,0,0,0,0,0,0,0,198,198,214,214,214,254,108,0,
95 | 0,0,0,0,0,0,0,0,198,108,56,56,56,108,198,0,0,0,0,0,0,0,0,0,198,198,198,198,
96 | 198,198,126,6,12,248,0,0,0,0,0,0,254,204,24,48,96,198,254,0,0,0,0,0,0,14,
97 | 24,24,24,112,24,24,24,24,14,0,0,0,0,0,0,24,24,24,24,0,24,24,24,24,24,0,0,
98 | 0,0,0,0,112,24,24,24,14,24,24,24,24,112,0,0,0,0,0,0,118,220,0,0,0,0,0,0,0,
99 | 0,0,0,0,0,0,0,0,0,16,56,108,198,198,198,254,0,0,0,0,0,0,0,60,102,194,192,
100 | 192,192,194,102,60,12,6,124,0,0,0,0,204,0,0,204,204,204,204,204,204,118,0,
101 | 0,0,0,0,12,24,48,0,124,198,254,192,192,198,124,0,0,0,0,0,16,56,108,0,120,
102 | 12,124,204,204,204,118,0,0,0,0,0,0,204,0,0,120,12,124,204,204,204,118,0,0,
103 | 0,0,0,96,48,24,0,120,12,124,204,204,204,118,0,0,0,0,0,56,108,56,0,120,12,
104 | 124,204,204,204,118,0,0,0,0,0,0,0,0,60,102,96,96,102,60,12,6,60,0,0,0,0,16,
105 | 56,108,0,124,198,254,192,192,198,124,0,0,0,0,0,0,198,0,0,124,198,254,192,
106 | 192,198,124,0,0,0,0,0,96,48,24,0,124,198,254,192,192,198,124,0,0,0,0,0,0,
107 | 102,0,0,56,24,24,24,24,24,60,0,0,0,0,0,24,60,102,0,56,24,24,24,24,24,60,0,
108 | 0,0,0,0,96,48,24,0,56,24,24,24,24,24,60,0,0,0,0,0,198,0,16,56,108,198,198,
109 | 254,198,198,198,0,0,0,0,56,108,56,0,56,108,198,198,254,198,198,198,0,0,0,
110 | 0,24,48,96,0,254,102,96,124,96,96,102,254,0,0,0,0,0,0,0,0,0,204,118,54,126,
111 | 216,216,110,0,0,0,0,0,0,62,108,204,204,254,204,204,204,204,206,0,0,0,0,0,
112 | 16,56,108,0,124,198,198,198,198,198,124,0,0,0,0,0,0,198,0,0,124,198,198,198,
113 | 198,198,124,0,0,0,0,0,96,48,24,0,124,198,198,198,198,198,124,0,0,0,0,0,48,
114 | 120,204,0,204,204,204,204,204,204,118,0,0,0,0,0,96,48,24,0,204,204,204,204,
115 | 204,204,118,0,0,0,0,0,0,198,0,0,198,198,198,198,198,198,126,6,12,120,0,0,
116 | 198,0,124,198,198,198,198,198,198,198,124,0,0,0,0,0,198,0,198,198,198,198,
117 | 198,198,198,198,124,0,0,0,0,0,24,24,60,102,96,96,96,102,60,24,24,0,0,0,0,
118 | 0,56,108,100,96,240,96,96,96,96,230,252,0,0,0,0,0,0,102,102,60,24,126,24,
119 | 126,24,24,24,0,0,0,0,0,248,204,204,248,196,204,222,204,204,204,198,0,0,0,
120 | 0,0,14,27,24,24,24,126,24,24,24,24,24,216,112,0,0,0,24,48,96,0,120,12,124,
121 | 204,204,204,118,0,0,0,0,0,12,24,48,0,56,24,24,24,24,24,60,0,0,0,0,0,24,48,
122 | 96,0,124,198,198,198,198,198,124,0,0,0,0,0,24,48,96,0,204,204,204,204,204,
123 | 204,118,0,0,0,0,0,0,118,220,0,220,102,102,102,102,102,102,0,0,0,0,118,220,
124 | 0,198,230,246,254,222,206,198,198,198,0,0,0,0,0,60,108,108,62,0,126,0,0,0,
125 | 0,0,0,0,0,0,0,56,108,108,56,0,124,0,0,0,0,0,0,0,0,0,0,0,48,48,0,48,48,96,
126 | 192,198,198,124,0,0,0,0,0,0,0,0,0,0,254,192,192,192,192,0,0,0,0,0,0,0,0,0,
127 | 0,0,254,6,6,6,6,0,0,0,0,0,0,192,192,194,198,204,24,48,96,220,134,12,24,62,
128 | 0,0,0,192,192,194,198,204,24,48,102,206,158,62,6,6,0,0,0,0,24,24,0,24,24,
129 | 24,60,60,60,24,0,0,0,0,0,0,0,0,0,54,108,216,108,54,0,0,0,0,0,0,0,0,0,0,0,
130 | 216,108,54,108,216,0,0,0,0,0,0,17,68,17,68,17,68,17,68,17,68,17,68,17,68,
131 | 17,68,85,170,85,170,85,170,85,170,85,170,85,170,85,170,85,170,221,119,221,
132 | 119,221,119,221,119,221,119,221,119,221,119,221,119,24,24,24,24,24,24,24,
133 | 24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,248,24,24,24,24,24,24,24,
134 | 24,24,24,24,24,24,248,24,248,24,24,24,24,24,24,24,24,54,54,54,54,54,54,54,
135 | 246,54,54,54,54,54,54,54,54,0,0,0,0,0,0,0,254,54,54,54,54,54,54,54,54,0,0,
136 | 0,0,0,248,24,248,24,24,24,24,24,24,24,24,54,54,54,54,54,246,6,246,54,54,54,
137 | 54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,0,0,0,0,0,
138 | 254,6,246,54,54,54,54,54,54,54,54,54,54,54,54,54,246,6,254,0,0,0,0,0,0,0,
139 | 0,54,54,54,54,54,54,54,254,0,0,0,0,0,0,0,0,24,24,24,24,24,248,24,248,0,0,
140 | 0,0,0,0,0,0,0,0,0,0,0,0,0,248,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
141 | 31,0,0,0,0,0,0,0,0,24,24,24,24,24,24,24,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
142 | 255,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,31,24,24,24,24,24,24,24,
143 | 24,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,24,24,24,24,24,24,24,255,24,24,24,24,
144 | 24,24,24,24,24,24,24,24,24,31,24,31,24,24,24,24,24,24,24,24,54,54,54,54,54,
145 | 54,54,55,54,54,54,54,54,54,54,54,54,54,54,54,54,55,48,63,0,0,0,0,0,0,0,0,
146 | 0,0,0,0,0,63,48,55,54,54,54,54,54,54,54,54,54,54,54,54,54,247,0,255,0,0,0,
147 | 0,0,0,0,0,0,0,0,0,0,255,0,247,54,54,54,54,54,54,54,54,54,54,54,54,54,55,48,
148 | 55,54,54,54,54,54,54,54,54,0,0,0,0,0,255,0,255,0,0,0,0,0,0,0,0,54,54,54,54,
149 | 54,247,0,247,54,54,54,54,54,54,54,54,24,24,24,24,24,255,0,255,0,0,0,0,0,0,
150 | 0,0,54,54,54,54,54,54,54,255,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,255,24,24,24,
151 | 24,24,24,24,24,0,0,0,0,0,0,0,255,54,54,54,54,54,54,54,54,54,54,54,54,54,54,
152 | 54,63,0,0,0,0,0,0,0,0,24,24,24,24,24,31,24,31,0,0,0,0,0,0,0,0,0,0,0,0,0,31,
153 | 24,31,24,24,24,24,24,24,24,24,0,0,0,0,0,0,0,63,54,54,54,54,54,54,54,54,54,
154 | 54,54,54,54,54,54,255,54,54,54,54,54,54,54,54,24,24,24,24,24,255,24,255,24,
155 | 24,24,24,24,24,24,24,24,24,24,24,24,24,24,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
156 | 0,31,24,24,24,24,24,24,24,24,255,255,255,255,255,255,255,255,255,255,255,
157 | 255,255,255,255,255,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,240,
158 | 240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,15,15,15,15,15,
159 | 15,15,15,15,15,15,15,15,15,15,15,255,255,255,255,255,255,255,0,0,0,0,0,0,
160 | 0,0,0,0,0,0,0,0,118,220,216,216,216,220,118,0,0,0,0,0,0,120,204,204,204,216,
161 | 204,198,198,198,204,0,0,0,0,0,0,254,198,198,192,192,192,192,192,192,192,0,
162 | 0,0,0,0,0,0,0,254,108,108,108,108,108,108,108,0,0,0,0,0,0,0,254,198,96,48,
163 | 24,48,96,198,254,0,0,0,0,0,0,0,0,0,126,216,216,216,216,216,112,0,0,0,0,0,
164 | 0,0,0,102,102,102,102,102,124,96,96,192,0,0,0,0,0,0,0,118,220,24,24,24,24,
165 | 24,24,0,0,0,0,0,0,0,126,24,60,102,102,102,60,24,126,0,0,0,0,0,0,0,56,108,
166 | 198,198,254,198,198,108,56,0,0,0,0,0,0,56,108,198,198,198,108,108,108,108,
167 | 238,0,0,0,0,0,0,30,48,24,12,62,102,102,102,102,60,0,0,0,0,0,0,0,0,0,126,219,
168 | 219,219,126,0,0,0,0,0,0,0,0,0,3,6,126,219,219,243,126,96,192,0,0,0,0,0,0,
169 | 28,48,96,96,124,96,96,96,48,28,0,0,0,0,0,0,0,124,198,198,198,198,198,198,
170 | 198,198,0,0,0,0,0,0,0,0,254,0,0,254,0,0,254,0,0,0,0,0,0,0,0,0,24,24,126,24,
171 | 24,0,0,255,0,0,0,0,0,0,0,48,24,12,6,12,24,48,0,126,0,0,0,0,0,0,0,12,24,48,
172 | 96,48,24,12,0,126,0,0,0,0,0,0,14,27,27,24,24,24,24,24,24,24,24,24,24,24,24,
173 | 24,24,24,24,24,24,24,216,216,216,112,0,0,0,0,0,0,0,0,24,24,0,126,0,24,24,
174 | 0,0,0,0,0,0,0,0,0,0,118,220,0,118,220,0,0,0,0,0,0,0,56,108,108,56,0,0,0,0,
175 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0,0,
176 | 0,0,0,0,0,15,12,12,12,12,12,236,108,108,60,28,0,0,0,0,0,216,108,108,108,108,
177 | 108,0,0,0,0,0,0,0,0,0,0,112,216,48,96,200,248,0,0,0,0,0,0,0,0,0,0,0,0,0,124,
178 | 124,124,124,124,124,124,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
179 | };
180 |
181 |
182 | static IGLYPHFONT ibuiltin_font = {
183 | 8, 16, _ifont_asc16
184 | };
185 |
186 |
187 | void ibitmap_draw_text(IBITMAP *dst, int x, int y, const char *string,
188 | const IRECT *clip, IUINT32 color, IUINT32 back, int additive)
189 | {
190 | ibitmap_draw_ascii(dst, &ibuiltin_font, x, y, string, clip, color, back,
191 | additive);
192 | }
193 |
194 |
195 | #ifdef _MSC_VER
196 | #pragma warning(disable:4996)
197 | #endif
198 |
199 | void ibitmap_printf(IBITMAP *dst, int x, int y, const IRECT *clip,
200 | IUINT32 color, IUINT32 back, int additive, const char *fmt, ...)
201 | {
202 | char buffer[4096];
203 | va_list argptr;
204 | va_start(argptr, fmt);
205 | vsprintf(buffer, fmt, argptr);
206 | va_end(argptr);
207 | ibitmap_draw_text(dst, x, y, buffer, clip, color, back, additive);
208 | }
209 |
210 |
--------------------------------------------------------------------------------
/pixellib/ibmfont.h:
--------------------------------------------------------------------------------
1 | //=====================================================================
2 | //
3 | // ibmfont.h - builtin font operation
4 | //
5 | // NOTE:
6 | // for more information, please see the readme file
7 | //
8 | //=====================================================================
9 | #ifndef __IBMFONT_H__
10 | #define __IBMFONT_H__
11 |
12 | #include "ibmcols.h"
13 |
14 |
15 | #ifdef __cplusplus
16 | extern "C" {
17 | #endif
18 |
19 |
20 | void ibitmap_draw_text(IBITMAP *dst, int x, int y, const char *string,
21 | const IRECT *clip, IUINT32 color, IUINT32 back, int additive);
22 |
23 | void ibitmap_printf(IBITMAP *dst, int x, int y, const IRECT *clip,
24 | IUINT32 color, IUINT32 back, int additive, const char *fmt, ...);
25 |
26 |
27 | #ifdef __cplusplus
28 | }
29 | #endif
30 |
31 | #endif
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/pixellib/ibmsse2.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/ibmsse2.c
--------------------------------------------------------------------------------
/pixellib/ibmsse2.h:
--------------------------------------------------------------------------------
1 | //=====================================================================
2 | //
3 | // ibmsse2.h - sse2 & mmx optimize
4 | //
5 | // NOTE:
6 | // for more information, please see the readme file
7 | //
8 | //=====================================================================
9 |
10 | #ifndef __IBMSSE2_H__
11 | #define __IBMSSE2_H__
12 |
13 | #include "ibmbits.h"
14 |
15 |
16 |
17 | //---------------------------------------------------------------------
18 | // platform detection
19 | //---------------------------------------------------------------------
20 | #if (defined(_WIN32) && !defined(WIN32))
21 | #define WIN32 _WIN32
22 | #elif (defined(WIN32) && !defined(_WIN32))
23 | #define _WIN32 WIN32
24 | #endif
25 |
26 | #if (defined(_WIN32) && !defined(_MSC_VER) && !defined(_WIN64))
27 | #ifndef __i386__
28 | #define __i386__
29 | #endif
30 | #elif defined(_MSC_VER)
31 | #if (defined(_M_IX86) && !defined(__i386__))
32 | #define __i386__
33 | #endif
34 | #endif
35 |
36 | #ifndef __i386__
37 | #if (defined(__386__) || defined(__I386__) || _M_IX86)
38 | #define __i386__
39 | #endif
40 | #endif
41 |
42 | #if (defined(__i386__) && !defined(__I386__))
43 | #define __I386__
44 | #endif
45 |
46 | #if (defined(__x86_64__) && !defined(__x86_64))
47 | #define __x86_64
48 | #endif
49 |
50 | #if (defined(__x86_64) && !defined(__x86_64__))
51 | #define __x86_64__
52 | #endif
53 |
54 | #if (defined(_M_AMD64)) && (!defined(__amd64__))
55 | #define __amd64__
56 | #endif
57 |
58 | #if (defined(__amd64) && !defined(__amd64__))
59 | #define __amd64__
60 | #endif
61 |
62 | #if (defined(__amd64__) && !defined(__amd64))
63 | #define __amd64
64 | #endif
65 |
66 | #if (defined(__i386__) || defined(__amd64__)) && (!defined(__x86__))
67 | #if !(defined(_MSC_VER) && defined(__amd64__))
68 | #define __x86__ // MSVC doesn't support inline assembly in x64
69 | #endif
70 | #endif
71 |
72 | //=====================================================================
73 | // i386 archtech support
74 | //=====================================================================
75 | #ifdef __x86__
76 |
77 |
78 | #ifndef ASMCODE
79 | #define ASMCODE
80 | //---------------------------------------------------------------------
81 | // basic inline asm operation code generation
82 | //---------------------------------------------------------------------
83 | #ifdef __GNUC__
84 | #define ASMCODE1(a) ".byte "#a"\n"
85 | #define ASMCODE2(a, b) ".byte "#a", "#b"\n"
86 | #define ASMCODE3(a, b, c) ".byte "#a", "#b", "#c"\n"
87 | #define ASMCODE4(a, b, c, d) ".byte "#a", "#b", "#c", "#d"\n"
88 | #define ASMCODE5(a, b, c, d, e) ".byte "#a", "#b", "#c", "#d", "#e"\n"
89 | #define ASMCODEW(n) ".short "#n"\n"
90 | #define ASMCODED(n) ".long "#n"\n"
91 | #define ASMALIGN(n) ".align "#n", 0x90\n"
92 | #define __ALIGNC__ ASMALIGN(8)
93 | #define __INLINEGNU__
94 | #ifndef __MACH__
95 | #define ASM_BEGIN
96 | #define ASM_ENDUP
97 | #ifdef __i386__
98 | #define ASM_REGS "esi", "edi", "eax", "ebx", "ecx", "edx"
99 | #else
100 | #define ASM_REGS "rsi", "rdi", "rax", "rbx", "rcx", "rdx"
101 | #endif
102 | #else
103 | #ifdef __i386__
104 | #define ASM_BEGIN " pushl %%ebx\n"
105 | #define ASM_ENDUP " popl %%ebx\n"
106 | #define ASM_REGS "esi", "edi", "eax", "ecx", "edx"
107 | #else
108 | #define ASM_BEGIN " push %%rbx\n"
109 | #define ASM_ENDUP " pop %%rbx\n"
110 | #define ASM_REGS "rsi", "rdi", "rax", "rcx", "rdx"
111 | #endif
112 | #endif
113 |
114 | #elif defined(_MSC_VER)
115 | #define ASMCODE1(a) _asm _emit (a)
116 | #define ASMCODE2(a, b) ASMCODE1(a) ASMCODE1(b)
117 | #define ASMCODE3(a, b, c) ASMCODE2(a, b) ASMCODE1(c)
118 | #define ASMCODE4(a, b, c, d) ASMCODE3(a, b, c) ASMCODE1(d)
119 | #define ASMCODE5(a, b, c, d, e) ASMCODE4(a, b, c, d) ASMCODE1(e)
120 | #define ASMCODEW(n) ASMCODE2(((n) AND 0xff), ((n) / 0x100))
121 | #define ASMCODED(n) ASMCODEW(n) ASMCODEW((n) / 0x10000)
122 | #define ASMALIGN(n) ALIGN n
123 | #define __ALIGNC__ ASMALIGN(8)
124 | #define __INLINEMSC__
125 | #define ASM_BEGIN
126 | #define ASM_ENDUP
127 |
128 | #elif (defined(__BORLANDC__) || defined(__WATCOMC__))
129 | #define ASMCODE1(a) DB a;
130 | #define ASMCODE2(a, b) DB a, b;
131 | #define ASMCODE3(a, b, c) DB a, b, c;
132 | #define ASMCODE4(a, b, c, d) DB a, b, c, d;
133 | #define ASMCODE5(a, b, c, d, e) DB a, b, c, d, e;
134 | #define ASMCODEW(n) DW n;
135 | #define ASMCODED(n) DD n;
136 | #define ASMALIGN(n) ALIGN n
137 | #pragma warn -8002
138 | #pragma warn -8004
139 | #pragma warn -8008
140 | #pragma warn -8012
141 | #pragma warn -8027
142 | #pragma warn -8057
143 | #pragma warn -8066
144 | #define __ALIGNC__ ASMALIGN(4)
145 | #define __INLINEMSC__
146 | //#ifdef __WATCOMC__
147 | #undef __ALIGNC__
148 | #define __ALIGNC__
149 | //#endif
150 | #define ASM_BEGIN
151 | #define ASM_ENDUP
152 | #endif
153 | #endif
154 |
155 | #endif
156 |
157 | //---------------------------------------------------------------------
158 | // PLATFORM DETECT
159 | //---------------------------------------------------------------------
160 | #if defined(__GNUC__)
161 | #if defined(__MMX__)
162 | #define __ARCH_MMX__
163 | #endif
164 | #if defined(__SSE__)
165 | #define __ARCH_SSE__
166 | #endif
167 | #if defined(__SSE2__)
168 | #define __ARCH_SSE2__
169 | #endif
170 | #elif defined(_MSC_VER) && defined(__x86__)
171 | #if !(defined(WIN64) || defined(_WIN64) || defined(__x86_64))
172 | #if _MSC_VER >= 1200
173 | #define __ARCH_MMX__
174 | #elif _MSC_VER >= 1300
175 | #define __ARCH_SSE__
176 | #elif _MSC_VER >= 1400
177 | #define __ARCH_SSE2__
178 | #endif
179 | #endif
180 | #endif
181 |
182 | #ifndef __IULONG_DEFINED
183 | #define __IULONG_DEFINED
184 | typedef ptrdiff_t ilong;
185 | typedef size_t iulong;
186 | #endif
187 |
188 | #ifndef __IINT64_DEFINED
189 | #define __IINT64_DEFINED
190 | #if defined(_MSC_VER) || defined(__BORLANDC__)
191 | typedef __int64 IINT64;
192 | #else
193 | typedef long long IINT64;
194 | #endif
195 | #endif
196 |
197 | #ifndef __IUINT64_DEFINED
198 | #define __IUINT64_DEFINED
199 | #if defined(_MSC_VER) || defined(__BORLANDC__)
200 | typedef unsigned __int64 IUINT64;
201 | #else
202 | typedef unsigned long long IUINT64;
203 | #endif
204 | #endif
205 |
206 | //---------------------------------------------------------------------
207 | // pixel load and store
208 | //---------------------------------------------------------------------
209 |
210 |
211 |
212 | //---------------------------------------------------------------------
213 | // INTERFACES
214 | //---------------------------------------------------------------------
215 | #ifdef __cplusplus
216 | extern "C" {
217 | #endif
218 |
219 | int pixellib_mmx_init(void);
220 |
221 | int pixellib_xmm_init(void);
222 |
223 | #ifdef __cplusplus
224 | }
225 | #endif
226 |
227 |
228 |
229 | #endif
230 |
231 |
232 |
--------------------------------------------------------------------------------
/pixellib/ibmwink.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/ibmwink.c
--------------------------------------------------------------------------------
/pixellib/ibmwink.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/ibmwink.h
--------------------------------------------------------------------------------
/pixellib/ikitwin.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/ikitwin.c
--------------------------------------------------------------------------------
/pixellib/ikitwin.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/ikitwin.h
--------------------------------------------------------------------------------
/pixellib/ipicture.c:
--------------------------------------------------------------------------------
1 | //=====================================================================
2 | //
3 | // ipicture.c - general picture file operation
4 | //
5 | // FEATURES:
6 | // * I/O stream support
7 | // * save and load tga/bmp/gif
8 | //
9 | // NOTE:
10 | // require ibitmap.h, ibmbits.h, ibmcols.h
11 | // for more information, please see the readme file
12 | //
13 | //=====================================================================
14 |
15 | #include "ibmbits.h"
16 | #include "ibmcols.h"
17 | #include "ipicture.h"
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 |
25 |
26 | //=====================================================================
27 | //
28 | // PICTURE DATA INTERFACE
29 | //
30 | // IMDIO - Media Data Input/Output Interface
31 | // PIXELS - Pixel Operation for Bitmaps
32 | // FIXUP - Pixel Format Fixing Up Interface
33 | //
34 | //=====================================================================
35 |
36 | //---------------------------------------------------------------------
37 | // Media Data Input/Output Interface
38 | //---------------------------------------------------------------------
39 | int is_getc(IMDIO *stream)
40 | {
41 | int ch;
42 | if (stream->_ungetc >= 0) {
43 | ch = (int)stream->_ungetc;
44 | stream->_ungetc = -1;
45 | } else {
46 | ch = (stream->getc)(stream);
47 | if (ch >= 0) stream->_cnt++;
48 | }
49 | return ch;
50 | }
51 |
52 | int is_putc(IMDIO *stream, int c)
53 | {
54 | int ch;
55 | ch = (stream->putc)(stream, c);
56 | if (ch >= 0) stream->_cnt++;
57 | return ch;
58 | }
59 |
60 | int is_ungetc(IMDIO *stream, int c)
61 | {
62 | if (stream->_ungetc >= 0) return -1;
63 | stream->_ungetc = (long)c;
64 | return c;
65 | }
66 |
67 | long is_reader(IMDIO *stream, void *buffer, long size)
68 | {
69 | unsigned char *lptr = (unsigned char*)buffer;
70 | long total = 0;
71 | int ch;
72 |
73 | for (ch = 0; total < size; total++) {
74 | ch = is_getc(stream);
75 | if (ch < 0) break;
76 | *lptr++ = (unsigned char)ch;
77 | }
78 | if (total == 0) return -1;
79 | return total;
80 | }
81 |
82 | long is_writer(IMDIO *stream, const void *buffer, long size)
83 | {
84 | unsigned char *lptr = (unsigned char*)buffer;
85 | long total = 0;
86 | int ch;
87 |
88 | for (ch = 0; total < size; total++) {
89 | ch = *lptr++;
90 | ch = is_putc(stream, ch);
91 | if (ch < 0) break;
92 | }
93 | if (total == 0) return -1;
94 | return total;
95 | }
96 |
97 | int is_igetw(IMDIO *stream)
98 | {
99 | int c1, c2;
100 | if ((c1 = is_getc(stream)) < 0) return -1;
101 | if ((c2 = is_getc(stream)) < 0) return -1;
102 | return c1 | (c2 << 8);
103 | }
104 |
105 | int is_iputw(IMDIO *stream, int w)
106 | {
107 | int c1 = (w & 0xFF), c2 = ((w >> 8) & 0xFF);
108 | if (is_putc(stream, c1) < 0) return -1;
109 | if (is_putc(stream, c2) < 0) return -1;
110 | return w;
111 | }
112 |
113 | long is_igetl(IMDIO *stream)
114 | {
115 | long c1, c2, c3, c4;
116 | if ((c1 = (long)is_getc(stream)) < 0) return -1;
117 | if ((c2 = (long)is_getc(stream)) < 0) return -1;
118 | if ((c3 = (long)is_getc(stream)) < 0) return -1;
119 | if ((c4 = (long)is_getc(stream)) < 0) return -1;
120 | return (c1 | (c2 << 8) | (c3 << 16) | (c4 << 24));
121 | }
122 |
123 | long is_iputl(IMDIO *stream, long l)
124 | {
125 | long c1, c2, c3, c4;
126 | c1 = (l & 0x000000FF) >> 0;
127 | c2 = (l & 0x0000FF00) >> 8;
128 | c3 = (l & 0x00FF0000) >> 16;
129 | c4 = (l & 0xFF000000) >> 24;
130 | if (is_putc(stream, c1) < 0) return -1;
131 | if (is_putc(stream, c2) < 0) return -1;
132 | if (is_putc(stream, c3) < 0) return -1;
133 | if (is_putc(stream, c4) < 0) return -1;
134 | return l;
135 | }
136 |
137 | int is_mgetw(IMDIO *stream)
138 | {
139 | int c1, c2;
140 | if ((c1 = is_getc(stream)) < 0) return -1;
141 | if ((c2 = is_getc(stream)) < 0) return -1;
142 | return (c1 << 8) | c2;
143 | }
144 |
145 | int is_mputw(IMDIO *stream, int w)
146 | {
147 | int c1 = (w >> 8) & 0xFF, c2 = (w & 0xFF);
148 | if (is_putc(stream, c1) < 0) return -1;
149 | if (is_putc(stream, c2) < 0) return -1;
150 | return w;
151 | }
152 |
153 | long is_mgetl(IMDIO *stream)
154 | {
155 | long c1, c2, c3, c4;
156 | if ((c1 = (long)is_getc(stream)) < 0) return -1;
157 | if ((c2 = (long)is_getc(stream)) < 0) return -1;
158 | if ((c3 = (long)is_getc(stream)) < 0) return -1;
159 | if ((c4 = (long)is_getc(stream)) < 0) return -1;
160 | return ((c1 << 24) | (c2 << 16) | (c3 << 8) | c4);
161 | }
162 |
163 | long is_mputl(IMDIO *stream, long l)
164 | {
165 | long c1, c2, c3, c4;
166 | c1 = (l & 0xFF000000) >> 24;
167 | c2 = (l & 0x00FF0000) >> 16;
168 | c3 = (l & 0x0000FF00) >> 8;
169 | c4 = (l & 0x000000FF);
170 | if (is_putc(stream, c1) < 0) return -1;
171 | if (is_putc(stream, c2) < 0) return -1;
172 | if (is_putc(stream, c3) < 0) return -1;
173 | if (is_putc(stream, c4) < 0) return -1;
174 | return l;
175 | }
176 |
177 | long is_getbits(IMDIO *stream, int count, int litend)
178 | {
179 | long data, bitc, bitd, mask, c, i;
180 | bitc = stream->_bitc;
181 | bitd = stream->_bitd;
182 | for (data = 0, i = 0; count > 0; ) {
183 | if (bitc == 0) {
184 | bitd = is_getc(stream);
185 | bitc = 8;
186 | if (bitd < 0) {
187 | bitd = 0;
188 | bitc = 0;
189 | data = -1;
190 | break;
191 | }
192 | }
193 | c = (count >= bitc) ? bitc : count;
194 | if (litend == 0) {
195 | data <<= c;
196 | data |= (bitd >> (8 - c)) & 0xff;
197 | bitd = (bitd << c) & 0xff;
198 | } else {
199 | mask = (1L << c) - 1;
200 | data |= (bitd & mask) << i;
201 | bitd >>= c;
202 | i += c;
203 | }
204 | count -= c;
205 | bitc -= c;
206 | }
207 | stream->_bitc = bitc;
208 | stream->_bitd = bitd;
209 | return data;
210 | }
211 |
212 | long is_putbits(IMDIO *stream, long data, int count, int litend)
213 | {
214 | long bitc, bitd, mask, c;
215 | bitc = stream->_bitc;
216 | bitd = stream->_bitd;
217 | for (; count > 0; ) {
218 | c = 8 - bitc;
219 | if (count < c) c = count;
220 | if (litend == 0) {
221 | mask = (data >> (count - c)) & 0xff;
222 | bitd |= (mask << (8 - c)) >> bitc;
223 | } else {
224 | mask = ((1L << c) - 1) & data;
225 | data >>= c;
226 | bitd |= mask << bitc;
227 | }
228 | bitc += c;
229 | count -= c;
230 | if (bitc >= 8) {
231 | if (is_putc(stream, bitd & 0xff) < 0) {
232 | return -1;
233 | }
234 | bitc = 0;
235 | bitd = 0;
236 | }
237 | }
238 | stream->_bitc = bitc;
239 | stream->_bitd = bitd;
240 | return 0;
241 | }
242 |
243 | void is_flushbits(IMDIO *stream, int isflushwrite, int litendian)
244 | {
245 | if (isflushwrite) {
246 | if (stream->_bitc != 0) {
247 | is_putbits(stream, 0, 8 - stream->_bitc, litendian);
248 | }
249 | }
250 | stream->_bitc = 0;
251 | stream->_bitd = 0;
252 | }
253 |
254 | long is_igetbits(IMDIO *stream, int count)
255 | {
256 | return is_getbits(stream, count, 1);
257 | }
258 |
259 | long is_mgetbits(IMDIO *stream, int count)
260 | {
261 | return is_getbits(stream, count, 0);
262 | }
263 |
264 | long is_iputbits(IMDIO *stream, long data, int count)
265 | {
266 | return is_putbits(stream, data, count, 1);
267 | }
268 |
269 | long is_mputbits(IMDIO *stream, long data, int count)
270 | {
271 | return is_putbits(stream, data, count, 0);
272 | }
273 |
274 | void is_iflushbits(IMDIO *stream, int isflushwrite)
275 | {
276 | is_flushbits(stream, isflushwrite, 1);
277 | }
278 |
279 | void is_mflushbits(IMDIO *stream, int isflushwrite)
280 | {
281 | is_flushbits(stream, isflushwrite, 0);
282 | }
283 |
284 | void is_seekcur(IMDIO *stream, long skip)
285 | {
286 | for (; skip > 0; skip--) is_getc(stream);
287 | }
288 |
289 |
290 | //---------------------------------------------------------------------
291 | // IBITMAP PIXEL OPERATION
292 | //---------------------------------------------------------------------
293 | #define _is_bmline(bmp, y) ((unsigned char*)((bmp)->line[y]))
294 |
295 | static inline IUINT32 _is_get3b(const void *p)
296 | {
297 | return _ipixel_fetch_24(p, 0);
298 | }
299 |
300 | static inline IUINT32 _is_put3b(void *p, IUINT32 c)
301 | {
302 | _ipixel_store_24(p, 0, c);
303 | return c;
304 | }
305 |
306 | #define _IS_HEADER1() do { \
307 | if (bmp == NULL) return 0; \
308 | if (x<0 || y<0 || x>=(int)bmp->w || y>=(int)bmp->h) \
309 | return 0; \
310 | } while (0)
311 |
312 | static inline IUINT32 _is_get8(const struct IBITMAP *bmp, int x, int y)
313 | {
314 | _IS_HEADER1();
315 | return _is_bmline(bmp, y)[x];
316 | }
317 |
318 | static inline IUINT32 _is_get15(const struct IBITMAP *bmp, int x, int y)
319 | {
320 | _IS_HEADER1();
321 | return ((IUINT16*)_is_bmline(bmp, y))[x];
322 | }
323 |
324 | static inline IUINT32 _is_get16(const struct IBITMAP *bmp, int x, int y)
325 | {
326 | _IS_HEADER1();
327 | return ((IUINT16*)_is_bmline(bmp, y))[x];
328 | }
329 |
330 | static inline IUINT32 _is_get24(const struct IBITMAP *bmp, int x, int y)
331 | {
332 | _IS_HEADER1();
333 | return _is_get3b(_is_bmline(bmp, y) + (x) * 3);
334 | }
335 |
336 | static inline IUINT32 _is_get32(const struct IBITMAP *bmp, int x, int y)
337 | {
338 | _IS_HEADER1();
339 | return ((IUINT32*)_is_bmline(bmp, y))[x];
340 | }
341 |
342 | static inline IUINT32 _is_put8(struct IBITMAP *bmp, int x, int y, IUINT32 c)
343 | {
344 | _IS_HEADER1();
345 | _is_bmline(bmp, y)[x] = (unsigned char)(c & 0xFF);
346 | return c;
347 | }
348 |
349 | static inline IUINT32 _is_put15(struct IBITMAP *bmp, int x, int y, IUINT32 c)
350 | {
351 | _IS_HEADER1();
352 | ((IUINT16*)_is_bmline(bmp, y))[x] = (IUINT16)(c & 0xFFFF);
353 | return c;
354 | }
355 |
356 | static inline IUINT32 _is_put16(struct IBITMAP *bmp, int x, int y, IUINT32 c)
357 | {
358 | _IS_HEADER1();
359 | ((IUINT16*)_is_bmline(bmp, y))[x] = (IUINT16)(c & 0xFFFF);
360 | return c;
361 | }
362 |
363 | static inline IUINT32 _is_put24(struct IBITMAP *bmp, int x, int y, IUINT32 c)
364 | {
365 | _IS_HEADER1();
366 | _is_put3b(_is_bmline(bmp, y) + (x) * 3, c);
367 | return c;
368 | }
369 |
370 | static inline IUINT32 _is_put32(struct IBITMAP *bmp, int x, int y, IUINT32 c)
371 | {
372 | _IS_HEADER1();
373 | ((IUINT32*)_is_bmline(bmp, y))[x] = c;
374 | return c;
375 | }
376 |
377 | static inline IUINT32 _is_getpx(const struct IBITMAP *bmp, int x, int y)
378 | {
379 | _IS_HEADER1();
380 | if (bmp->bpp == 8) return _is_get8(bmp, x, y);
381 | else if (bmp->bpp == 15) return _is_get15(bmp, x, y);
382 | else if (bmp->bpp == 16) return _is_get16(bmp, x, y);
383 | else if (bmp->bpp == 24) return _is_get24(bmp, x, y);
384 | else if (bmp->bpp == 32) return _is_get32(bmp, x, y);
385 | return 0;
386 | }
387 |
388 | static inline IUINT32 _is_putpx(struct IBITMAP *bmp, int x, int y, IUINT32 c)
389 | {
390 | _IS_HEADER1();
391 | if (bmp->bpp == 8) return _is_put8(bmp, x, y, c);
392 | else if (bmp->bpp == 15) return _is_put15(bmp, x, y, c);
393 | else if (bmp->bpp == 16) return _is_put16(bmp, x, y, c);
394 | else if (bmp->bpp == 24) return _is_put24(bmp, x, y, c);
395 | else if (bmp->bpp == 32) return _is_put32(bmp, x, y, c);
396 | return 0;
397 | }
398 |
399 | int _ibitmap_guess_pixfmt(const IBITMAP *bmp)
400 | {
401 | int fmt;
402 | fmt = ibitmap_pixfmt_get(bmp);
403 | if (fmt < 0) {
404 | if (bmp->bpp == 8) return IPIX_FMT_C8;
405 | if (bmp->bpp == 15) return IPIX_FMT_X1R5G5B5;
406 | if (bmp->bpp == 16) return IPIX_FMT_R5G6B5;
407 | if (bmp->bpp == 24) return IPIX_FMT_R8G8B8;
408 | if (bmp->bpp == 32) return IPIX_FMT_A8R8G8B8;
409 | }
410 | return fmt;
411 | }
412 |
413 | IUINT32 _im_color_get(int fmt, IUINT32 c, const IRGB *pal)
414 | {
415 | IINT32 r, g, b, a;
416 | if (ipixelfmt[fmt].type == IPIX_FMT_TYPE_INDEX) {
417 | return IRGBA_TO_A8R8G8B8(pal[c].r, pal[c].g, pal[c].b, 255);
418 | }
419 | IRGBA_DISEMBLE(fmt, c, r, g, b, a);
420 | return IRGBA_TO_A8R8G8B8(r, g, b, a);
421 | }
422 |
423 |
424 | #undef _IS_HEADER1
425 |
426 | //---------------------------------------------------------------------
427 | // local definition
428 | //---------------------------------------------------------------------
429 | typedef struct IBITMAP ibitmap_t;
430 | long _is_perrno = 0;
431 |
432 | void _is_perrno_set(long v) { _is_perrno = v; }
433 | long _is_perrno_get(void) { return _is_perrno; }
434 |
435 | //---------------------------------------------------------------------
436 | // stream operation interface
437 | //---------------------------------------------------------------------
438 | #define IRWCHECK(s, v) do { if ((s)->_code != (v)) return -1; } while(0)
439 | static int iproc_getc_mem(struct IMDIO *stream)
440 | {
441 | IRWCHECK(stream, 0);
442 | if (stream->_pos < stream->_len)
443 | return ((unsigned char*)(stream->data))[stream->_pos++];
444 | return -1;
445 | }
446 |
447 | static int iproc_putc_mem(struct IMDIO *stream, int c)
448 | {
449 | unsigned char ch = (unsigned char)c;
450 | IRWCHECK(stream, 0);
451 | if (stream->_pos == stream->_len) return -1;
452 | else if (stream->_pos < stream->_len) {
453 | ((unsigned char*)(stream->data))[stream->_pos++] = ch;
454 | }
455 | if (stream->_pos > stream->_len) stream->_len = stream->_pos;
456 | return c;
457 | }
458 |
459 | static int iproc_getc_file(struct IMDIO *stream)
460 | {
461 | IRWCHECK(stream, 1);
462 | return fgetc((FILE*)(stream->data));
463 | }
464 |
465 | static int iproc_putc_file(struct IMDIO *stream, int c)
466 | {
467 | IRWCHECK(stream, 1);
468 | return fputc(c, (FILE*)(stream->data));
469 | }
470 |
471 | int is_init_mem(IMDIO *stream, const void *lptr, long size)
472 | {
473 | stream->_code = 0;
474 | stream->_pos = 0;
475 | stream->_len = size;
476 | stream->_bitc = 0;
477 | stream->_bitd = 0;
478 | stream->_ungetc = -1;
479 | stream->data = (void*)lptr;
480 | stream->getc = iproc_getc_mem;
481 | stream->putc = iproc_putc_mem;
482 | return 0;
483 | }
484 |
485 | #ifdef _MSC_VER
486 | #pragma warning(disable:4996)
487 | #endif
488 |
489 | int is_open_file(IMDIO *stream, const char *filename, const char *rw)
490 | {
491 | stream->_code = -1;
492 | stream->data = fopen(filename, rw);
493 | if (stream->data == NULL) return -1;
494 | stream->_code = 1;
495 | stream->_bitc = 0;
496 | stream->_bitd = 0;
497 | stream->_ungetc = -1;
498 | stream->getc = iproc_getc_file;
499 | stream->putc = iproc_putc_file;
500 | return 0;
501 | }
502 |
503 | int is_close_file(IMDIO *stream)
504 | {
505 | IRWCHECK(stream, 1);
506 | fclose((FILE*)(stream->data));
507 | return 0;
508 | }
509 |
510 |
511 | void *is_read_marked_block(IMDIO *stream, const unsigned char *mark,
512 | int marksize, size_t *nbytes_readed)
513 | {
514 | static const unsigned char dmark[2] = { 0, 0 };
515 | unsigned char *data;
516 | unsigned char *buffer;
517 | size_t block = 0;
518 | size_t nsize = 0;
519 | int nbuffered = 0;
520 | int index = 0;
521 |
522 | if (stream == NULL)
523 | return NULL;
524 |
525 | buffer = (unsigned char*)malloc(marksize + 10);
526 |
527 | if (buffer == NULL)
528 | return NULL;
529 |
530 | data = (unsigned char*)malloc(256);
531 | block = 256;
532 |
533 | if (data == NULL) {
534 | free(buffer);
535 | return NULL;
536 | }
537 |
538 | if (mark == NULL) mark = dmark;
539 |
540 | while (1) {
541 | int ch;
542 | ch = is_getc(stream);
543 | if (ch < 0) break;
544 | buffer[index] = (unsigned char)ch;
545 | data[nsize++] = (unsigned char)ch;
546 |
547 | if (nsize >= block) {
548 | unsigned char *tmp = (unsigned char*)malloc(block * 2);
549 | if (tmp != NULL) {
550 | memcpy(tmp, data, nsize);
551 | free(data);
552 | data = tmp;
553 | block = block * 2;
554 | } else {
555 | nsize = 0;
556 | }
557 | }
558 |
559 | if (++nbuffered >= marksize && mark && marksize > 0) {
560 | int i, j, k;
561 | for (i = index, j = marksize - 1, k = 0; j >= 0; j--, k++) {
562 | if (buffer[i] != mark[j]) break;
563 | if (--i < 0) i = marksize - 1;
564 | }
565 | if (k == marksize) break;
566 | }
567 | if (++index >= marksize) index = 0;
568 | }
569 |
570 | free(buffer);
571 |
572 | buffer = NULL;
573 | if (nsize > 0) {
574 | buffer = (unsigned char*)malloc(nsize);
575 | }
576 |
577 | if (buffer == NULL || nsize == 0) {
578 | free(data);
579 | if (nbytes_readed) *nbytes_readed = 0;
580 | return NULL;
581 | }
582 |
583 | memcpy(buffer, data, nsize);
584 | if (nbytes_readed) *nbytes_readed = nsize;
585 | free(data);
586 |
587 | return buffer;
588 | }
589 |
590 |
591 |
592 | //=====================================================================
593 | //
594 | // bmp - Windows/OS2 IBITMAP Format
595 | //
596 | // decoding program - idcolor.h
597 | //
598 | //=====================================================================
599 | #define IBI_RGB 0
600 | #define IBI_RLE8 1
601 | #define IBI_RLE4 2
602 | #define IBI_BITFIELDS 3
603 |
604 | #define IOS2INFOHEADERSIZE 12
605 | #define IWININFOHEADERSIZE 40
606 |
607 |
608 | typedef struct _IBITMAPFILEHEADER
609 | {
610 | IUINT32 bfType;
611 | IUINT32 bfSize;
612 | IUINT16 bfReserved1;
613 | IUINT16 bfReserved2;
614 | IUINT32 bfOffBits;
615 | } IBITMAPFILEHEADER;
616 |
617 |
618 | typedef struct _IBITMAPINFOHEADER
619 | {
620 | IUINT32 biWidth;
621 | IUINT32 biHeight;
622 | IUINT16 biBitCount;
623 | IUINT32 biCompression;
624 | } IBITMAPINFOHEADER;
625 |
626 |
627 | //---------------------------------------------------------------------
628 | // bmp - read_bmfileheader
629 | //---------------------------------------------------------------------
630 | static int iread_bmfileheader(IMDIO *stream, IBITMAPFILEHEADER *fileheader)
631 | {
632 | fileheader->bfType = is_igetw(stream);
633 | fileheader->bfSize= is_igetl(stream);
634 | fileheader->bfReserved1= is_igetw(stream);
635 | fileheader->bfReserved2= is_igetw(stream);
636 | fileheader->bfOffBits= is_igetl(stream);
637 |
638 | if (fileheader->bfType != 0x4D42) return -1;
639 |
640 | return 0;
641 | }
642 |
643 | //---------------------------------------------------------------------
644 | // bmp - read_bminfoheader
645 | //---------------------------------------------------------------------
646 | static int iread_bminfoheader(IMDIO *stream, IBITMAPINFOHEADER *infoheader,
647 | int ihsize)
648 | {
649 | long data[20];
650 |
651 | if (ihsize == IWININFOHEADERSIZE) {
652 | data[0] = is_igetl(stream); /* IUINT32 biWidth......... */
653 | data[1] = is_igetl(stream); /* IUINT32 biHeight........ */
654 | data[2] = is_igetw(stream); /* IUINT16 biPlanes........ */
655 | data[3] = is_igetw(stream); /* IUINT16 biBitCount...... */
656 | data[4] = is_igetl(stream); /* IUINT32 biCompression... */
657 | data[5] = is_igetl(stream); /* IUINT32 biSizeImage..... */
658 | data[6] = is_igetl(stream); /* IUINT32 biXPelsPerMeters */
659 | data[7] = is_igetl(stream); /* IUINT32 biYPelsPerMeters */
660 | data[8] = is_igetl(stream); /* IUINT32 biClrUsed....... */
661 | data[9] = is_igetl(stream); /* IUINT32 biClrImportant.. */
662 |
663 | infoheader->biWidth = data[0];
664 | infoheader->biHeight = data[1];
665 | infoheader->biBitCount = (IUINT16)data[3];
666 | infoheader->biCompression = data[4];
667 | }
668 | else
669 | if (ihsize == IOS2INFOHEADERSIZE) {
670 | data[0] = is_igetw(stream); /* IUINT16 biWidth......... */
671 | data[1] = is_igetw(stream); /* IUINT16 biHeight........ */
672 | data[2] = is_igetw(stream); /* IUINT16 biPlanes........ */
673 | data[3] = is_igetw(stream); /* IUINT16 biBitCount...... */
674 |
675 | infoheader->biWidth = data[0];
676 | infoheader->biHeight= data[1];
677 | infoheader->biBitCount = (IUINT16)data[3];
678 | infoheader->biCompression = 0;
679 | }
680 | else {
681 | return -1;
682 | }
683 |
684 | return 0;
685 | }
686 |
687 | //---------------------------------------------------------------------
688 | // bmp - read_bmicolors
689 | //---------------------------------------------------------------------
690 | static void ibmp_read_bmicolors(int ncols, IRGB *pal, IMDIO *stream,
691 | int win_flag)
692 | {
693 | int i;
694 | for (i = 0; i < ncols; i++) {
695 | pal[i].b = is_getc(stream);
696 | pal[i].g = is_getc(stream);
697 | pal[i].r = is_getc(stream);
698 | if (win_flag) is_getc(stream);
699 | }
700 | }
701 |
702 | //---------------------------------------------------------------------
703 | // bmp - read_image
704 | //---------------------------------------------------------------------
705 | static void ibmp_read_image(IMDIO *stream, ibitmap_t *bmp, const
706 | IBITMAPINFOHEADER *infoheader)
707 | {
708 | long line, start, length;
709 | long i, j, k, a, nbytes;
710 | IUINT32 n;
711 | unsigned char b[32];
712 | IRGB c;
713 |
714 | for (start = 0; start < (long)infoheader->biHeight; start++) {
715 | line = infoheader->biHeight - start - 1;
716 | length = (long)infoheader->biWidth;
717 |
718 | switch (infoheader->biBitCount) {
719 |
720 | case 1:
721 | for (i = 0; i < length; i++) {
722 | j = i % 32;
723 | if (j == 0) {
724 | n = is_mgetl(stream);
725 | for (k = 0; k < 32; k++) {
726 | b[31 - k] = (char)(n & 1);
727 | n = n >> 1;
728 | }
729 | }
730 | _is_put8(bmp, i, line, b[j]);
731 | }
732 | break;
733 |
734 | case 4:
735 | for (i = 0; i < length; i++) {
736 | j = i % 8;
737 | if (j == 0) {
738 | n = is_igetl(stream);
739 | for (k = 0; k < 4; k++) {
740 | b[k * 2 + 1] = (IUINT8)(((n & 0xFF) >> 0) & 0x0F);
741 | b[k * 2 + 0] = (IUINT8)(((n & 0xFF) >> 4) & 0x0F);
742 | n = n >> 8;
743 | }
744 | }
745 | _is_put8(bmp, i, line, b[j]);
746 | }
747 | break;
748 |
749 | case 8:
750 | for (i = 0; i < length; i++) {
751 | _is_put8(bmp, i, line, is_getc(stream));
752 | }
753 | break;
754 |
755 | case 24:
756 | for (nbytes = 0, i = 0; i < length; i++, nbytes += 3) {
757 | IUINT32 cc;
758 | c.b = is_getc(stream);
759 | c.g = is_getc(stream);
760 | c.r = is_getc(stream);
761 | cc = IRGBA_TO_R8G8B8(c.r, c.g, c.b, 255);
762 | _is_put24(bmp, i, line, cc);
763 | }
764 | nbytes = nbytes % 4;
765 | for (i = nbytes; nbytes != 0 && i < 4; i++) is_getc(stream);
766 | break;
767 |
768 | case 32:
769 | for (i = 0; i < length; i++) {
770 | c.b = is_getc(stream);
771 | c.g = is_getc(stream);
772 | c.r = is_getc(stream);
773 | a = is_getc(stream);
774 | if (bmp->bpp == 32) {
775 | IUINT32 cc = IRGBA_TO_A8R8G8B8(c.r, c.g, c.b, a);
776 | _is_put32(bmp, i, line, cc);
777 | } else {
778 | IUINT32 cc = IRGBA_TO_A8R8G8B8(c.r, c.g, c.b, a);
779 | _is_put24(bmp, i, line, cc);
780 | }
781 | }
782 | break;
783 | }
784 | }
785 | }
786 |
787 | //---------------------------------------------------------------------
788 | // bmp - read_bitfields_image
789 | //---------------------------------------------------------------------
790 | static void ibmp_read_bitfields_image(IMDIO *stream, ibitmap_t *bmp,
791 | IBITMAPINFOHEADER *infoheader)
792 | {
793 | long i, j;
794 | long bpp;
795 | int bytes_per_pixel;
796 | int red, grn, blu;
797 | IUINT32 buffer;
798 |
799 | bpp = bmp->bpp;
800 | bytes_per_pixel = (bpp + 7) / 8;
801 |
802 | for (j = (long)infoheader->biHeight - 1; j >= 0; j--) {
803 | for (i = 0; i < (long)infoheader->biWidth; i++) {
804 |
805 | buffer = 0;
806 | if (bytes_per_pixel == 1) buffer = is_getc(stream);
807 | else if (bytes_per_pixel == 2) buffer = is_igetw(stream);
808 | else if (bytes_per_pixel == 3) {
809 | buffer = is_getc(stream);
810 | buffer |= is_getc(stream) << 8;
811 | buffer |= is_getc(stream) << 16;
812 | }
813 | else if (bytes_per_pixel == 4) {
814 | buffer = (IUINT32)is_igetl(stream);
815 | }
816 |
817 | if (bpp == 15) {
818 | red = (buffer >> 10) & 0x1f;
819 | grn = (buffer >> 5) & 0x1f;
820 | blu = (buffer) & 0x1f;
821 | buffer = (red << 10) |
822 | (grn << 5) |
823 | (blu << 0);
824 | }
825 | else if (bpp == 16) {
826 | red = (buffer >> 11) & 0x1f;
827 | grn = (buffer >> 5) & 0x3f;
828 | blu = (buffer) & 0x1f;
829 | buffer = (red << 11) |
830 | (grn << 5) |
831 | (blu << 0);
832 | }
833 | else {
834 | red = (buffer >> 16) & 0xff;
835 | grn = (buffer >> 8) & 0xff;
836 | blu = (buffer) & 0xff;
837 | buffer = (red << 24) |
838 | (grn << 16) |
839 | (blu << 0);
840 | }
841 |
842 | if (bytes_per_pixel == 1) _is_put8(bmp, i, j, buffer);
843 | else if (bytes_per_pixel == 2) _is_put16(bmp, i, j, buffer);
844 | else if (bytes_per_pixel == 3) _is_put24(bmp, i, j, buffer);
845 | else _is_put32(bmp, i, j, buffer);
846 | }
847 | }
848 | }
849 |
850 | //---------------------------------------------------------------------
851 | // bmp - read_rle_image
852 | //---------------------------------------------------------------------
853 | static void ibmp_read_rle_image(IMDIO *stream, ibitmap_t *bmp,
854 | IBITMAPINFOHEADER *infoheader)
855 | {
856 | unsigned char count, val, val0;
857 | unsigned char b[8];
858 | long line, j, k, pos, bpp;
859 | long eolflag, eopicflag;
860 |
861 | line = infoheader->biHeight - 1;
862 | bpp = (infoheader->biCompression == IBI_RLE8)? 8 : 4;
863 | val = 0;
864 |
865 | for (eopicflag = 0; eopicflag == 0; ) {
866 | for (eolflag = 0, pos = 0; eolflag == 0 && eopicflag == 0; ) {
867 | count = is_getc(stream);
868 | val0 = is_getc(stream);
869 | if (count > 0) {
870 | b[1] = val0 & 15;
871 | b[0] = (val0 >> 4) & 15;
872 | for (j = 0; j < count; j++, pos++) {
873 | val = (bpp == 8)? val0 : b[j % 2];
874 | _is_put8(bmp, pos, line, val);
875 | }
876 | }
877 | else {
878 | if (val == 0) eolflag = 1;
879 | else if (val == 1) eopicflag = 1;
880 | else if (val == 2) {
881 | pos += is_getc(stream);
882 | line -= is_getc(stream);
883 | } else {
884 | for (j = 0; j < val; j++, pos++) {
885 | if (bpp == 8) val = is_getc(stream);
886 | else {
887 | if ((j % 4) == 0) {
888 | val0 = is_igetw(stream);
889 | for (k = 0; k < 2; k++) {
890 | b[2 * k + 1] = val0 & 15;
891 | val0 = val0 >> 4;
892 | b[2 * k] = val0 & 15;
893 | val0 = val0 >> 4;
894 | }
895 | }
896 | val = b[j % 4];
897 | }
898 | _is_put8(bmp, pos, line, val);
899 | }
900 | if (j % 2 == 1 && bpp == 8) val0 = is_getc(stream);
901 | }
902 | }
903 | if (pos >= (long)infoheader->biWidth) eolflag = 1;
904 | }
905 | if (--line < 0) eopicflag = 1;
906 | }
907 | }
908 |
909 | //---------------------------------------------------------------------
910 | // bmp - iload_bmp_stream
911 | //---------------------------------------------------------------------
912 | struct IBITMAP *iload_bmp_stream(IMDIO *stream, IRGB *pal)
913 | {
914 | IBITMAPFILEHEADER fileheader;
915 | IBITMAPINFOHEADER infoheader;
916 | struct IBITMAP *bmp;
917 | long want_palette = 1;
918 | long ncol;
919 | IUINT32 biSize;
920 | int bpp, dest_depth;
921 | IRGB tmppal[256];
922 |
923 | assert(stream);
924 |
925 | _is_perrno_set(0);
926 |
927 | if (!pal) {
928 | want_palette = 0;
929 | pal = tmppal;
930 | }
931 |
932 | if (iread_bmfileheader(stream, &fileheader) != 0) {
933 | _is_perrno_set(1);
934 | return NULL;
935 | }
936 |
937 | biSize = is_igetl(stream);
938 |
939 | if (iread_bminfoheader(stream, &infoheader, biSize) != 0) {
940 | _is_perrno_set(2);
941 | return NULL;
942 | }
943 |
944 | if (biSize == IWININFOHEADERSIZE) {
945 | ncol = (fileheader.bfOffBits - 54) / 4;
946 | if (infoheader.biCompression != IBI_BITFIELDS)
947 | ibmp_read_bmicolors(ncol, pal, stream, 1);
948 | }
949 | else if (biSize == IOS2INFOHEADERSIZE) {
950 | ncol = (fileheader.bfOffBits - 26) / 3;
951 | if (infoheader.biCompression != IBI_BITFIELDS)
952 | ibmp_read_bmicolors(ncol, pal, stream, 0);
953 | } else {
954 | _is_perrno_set(3);
955 | return NULL;
956 | }
957 |
958 | if (infoheader.biBitCount == 24) bpp = 24;
959 | else if (infoheader.biBitCount == 16) bpp = 16;
960 | else if (infoheader.biBitCount == 32) bpp = 32;
961 | else bpp = 8;
962 |
963 | if (infoheader.biCompression == IBI_BITFIELDS) {
964 | IUINT32 redMask = is_igetl(stream);
965 | IUINT32 grnMask = is_igetl(stream);
966 | IUINT32 bluMask = is_igetl(stream);
967 | (void)grnMask;
968 | if ((bluMask == 0x001f) && (redMask == 0x7C00)) bpp = 15;
969 | else if ((bluMask == 0x001f) && (redMask == 0xF800)) bpp = 16;
970 | else if ((bluMask == 0x0000FF) && (redMask == 0xFF0000)) bpp = 32;
971 | else {
972 | _is_perrno_set(4);
973 | return NULL;
974 | }
975 | }
976 |
977 | bmp = ibitmap_create(infoheader.biWidth, infoheader.biHeight, bpp);
978 | dest_depth = bpp;
979 |
980 | if (!bmp) {
981 | _is_perrno_set(5);
982 | return NULL;
983 | }
984 |
985 | switch (infoheader.biCompression)
986 | {
987 | case IBI_RGB:
988 | ibmp_read_image(stream, bmp, &infoheader);
989 | break;
990 | case IBI_RLE8:
991 | case IBI_RLE4:
992 | ibmp_read_rle_image(stream, bmp, &infoheader);
993 | break;
994 | case IBI_BITFIELDS:
995 | ibmp_read_bitfields_image(stream, bmp, &infoheader);
996 | break;
997 | default:
998 | ibitmap_release(bmp);
999 | bmp = NULL;
1000 | _is_perrno_set(6);
1001 | break;
1002 | }
1003 |
1004 | if (dest_depth != bpp) {
1005 | if ((bpp != 8) && (!want_palette)) pal = NULL;
1006 | }
1007 |
1008 | ibitmap_pixfmt_set(bmp, ibitmap_pixfmt_guess(bmp));
1009 |
1010 | /* construct a fake palette if 8-bit mode is not involved */
1011 | if ((bpp != 8) && (dest_depth != 8) && want_palette) {
1012 | //_igenerate_332_palette(pal);
1013 | }
1014 |
1015 | return bmp;
1016 | }
1017 |
1018 | //---------------------------------------------------------------------
1019 | // bmp - isave_bmp_stream
1020 | //---------------------------------------------------------------------
1021 | int isave_bmp_stream(IMDIO *stream, struct IBITMAP *bmp, const IRGB *pal)
1022 | {
1023 | IUINT32 c, p;
1024 | long i, j;
1025 | IRGB tmppal[256];
1026 | int bfSize;
1027 | int biSizeImage;
1028 | int depth;
1029 | int bpp;
1030 | int filler;
1031 | int fmt;
1032 |
1033 | assert(bmp);
1034 | assert(stream);
1035 |
1036 | depth = bmp->bpp;
1037 | bpp = (depth == 8) ? 8 : 24;
1038 | filler = 3 - ((bmp->w * (bpp / 8) - 1) & 3);
1039 |
1040 | if (!pal) {
1041 | memcpy(tmppal, _ipaletted, 256 * sizeof(IRGB));
1042 | pal = tmppal;
1043 | }
1044 |
1045 | if (bpp == 8) {
1046 | biSizeImage = (bmp->w + filler) * bmp->h;
1047 | bfSize = (54 + 256 * 4 + biSizeImage);
1048 | } else {
1049 | biSizeImage = (bmp->w * 3 + filler) * bmp->h;
1050 | bfSize = 54 + biSizeImage;
1051 | }
1052 |
1053 | _is_perrno_set(0);
1054 |
1055 | /* file_header */
1056 | is_iputw(stream, 0x4D42); /* bfType ("BM") */
1057 | is_iputl(stream, bfSize); /* bfSize */
1058 | is_iputw(stream, 0); /* bfReserved1 */
1059 | is_iputw(stream, 0); /* bfReserved2 */
1060 |
1061 | if (bpp == 8) is_iputl(stream, 54 + 256 * 4);
1062 | else is_iputl(stream, 54);
1063 |
1064 | /* info_header */
1065 | is_iputl(stream, 40); /* biSize */
1066 | is_iputl(stream, (long)bmp->w); /* biWidth */
1067 | is_iputl(stream, (long)bmp->h); /* biHeight */
1068 | is_iputw(stream, 1); /* biPlanes */
1069 | is_iputw(stream, bpp); /* biBitCount */
1070 | is_iputl(stream, 0); /* biCompression */
1071 | is_iputl(stream, biSizeImage); /* biSizeImage */
1072 | is_iputl(stream, 0xB12); /* (0xB12 = 72 dpi) */
1073 | is_iputl(stream, 0xB12); /* biYPelsPerMeter */
1074 |
1075 | if (bpp == 8) {
1076 | is_iputl(stream, 256); /* biClrUsed */
1077 | is_iputl(stream, 256); /* biClrImportant */
1078 | for (i = 0; i < 256; i++) {
1079 | is_putc(stream, pal[i].b);
1080 | is_putc(stream, pal[i].g);
1081 | is_putc(stream, pal[i].r);
1082 | is_putc(stream, 0);
1083 | }
1084 | } else {
1085 | is_iputl(stream, 0); /* biClrUsed */
1086 | is_iputl(stream, 0); /* biClrImportant */
1087 | }
1088 |
1089 | fmt = _ibitmap_guess_pixfmt(bmp);
1090 |
1091 | /* image data */
1092 | for (j = (long)bmp->h - 1; j >= 0; j--) {
1093 | for (i = 0; i < (long)bmp->w; i++) {
1094 | c = _is_getpx(bmp, i, j);
1095 | p = _im_color_get(fmt, c, pal);
1096 | if (bpp == 8) {
1097 | is_putc(stream, (long)c);
1098 | } else {
1099 | is_putc(stream, (int)((p >> 0) & 0xFF));
1100 | is_putc(stream, (int)((p >> 8) & 0xFF));
1101 | is_putc(stream, (int)((p >> 16) & 0xFF));
1102 | }
1103 | }
1104 | for (i = 0; i < (long)filler; i++) is_putc(stream, 0);
1105 | }
1106 |
1107 | return 0;
1108 | }
1109 |
1110 | //---------------------------------------------------------------------
1111 | // bmp - isave_bmp_file
1112 | //---------------------------------------------------------------------
1113 | int isave_bmp_file(const char *file, struct IBITMAP *bmp, const IRGB *pal)
1114 | {
1115 | IMDIO stream;
1116 | int retval;
1117 |
1118 | if (is_open_file(&stream, file, "wb")) return -1;
1119 | retval = isave_bmp_stream(&stream, bmp, pal);
1120 | is_close_file(&stream);
1121 |
1122 | return retval;
1123 | }
1124 |
1125 |
1126 | //=====================================================================
1127 | //
1128 | // tga - Tagged Graphics (Truevision Inc.) Format
1129 | //
1130 | // decoding program - idcolor.h
1131 | //
1132 | //=====================================================================
1133 |
1134 |
1135 | //---------------------------------------------------------------------
1136 | // tga - single_tga_readn
1137 | //---------------------------------------------------------------------
1138 | static IUINT32 single_tga_readn(IMDIO *stream, int bpp)
1139 | {
1140 | IUINT32 r, g, b, a, c;
1141 |
1142 | if (bpp == 8) return is_getc(stream);
1143 | if (bpp == 15) {
1144 | c = is_igetw(stream);
1145 | r = _ipixel_scale_5[(c >> 10) & 0x1F];
1146 | g = _ipixel_scale_5[(c >> 5) & 0x1F];
1147 | b = _ipixel_scale_5[(c >> 0) & 0x1F];
1148 | return IRGBA_TO_X1R5G5B5(r, g, b, 255);
1149 | }
1150 | if (bpp == 16) {
1151 | c = is_igetw(stream);
1152 | r = _ipixel_scale_5[(c >> 11) & 0x1F];
1153 | g = _ipixel_scale_6[(c >> 5) & 0x3F];
1154 | b = _ipixel_scale_5[(c >> 0) & 0x1F];
1155 | return IRGBA_TO_R5G6B5(r, g, b, 255);
1156 | }
1157 | if (bpp != 24 && bpp != 32) {
1158 | return 0xffffffff;
1159 | }
1160 |
1161 | b = is_getc(stream);
1162 | g = is_getc(stream);
1163 | r = is_getc(stream);
1164 | a = (bpp == 32)? is_getc(stream) : 0;
1165 | c = IRGBA_TO_A8R8G8B8(r, g, b, a);
1166 | if (bpp == 24) c &= 0xffffff;
1167 |
1168 | return c;
1169 | }
1170 |
1171 | //---------------------------------------------------------------------
1172 | // tga - raw_tga_readn
1173 | //---------------------------------------------------------------------
1174 | static void *raw_tga_readn(void *b, int w, int bpp, IMDIO *stream)
1175 | {
1176 | unsigned char *lptr = (unsigned char*)b;
1177 | IUINT32 c, n;
1178 |
1179 | n = (bpp + 7) >> 3;
1180 | for (; w > 0; w--, lptr += n) {
1181 | c = single_tga_readn(stream, bpp);
1182 | if (n == 1) _ipixel_store_8(lptr, 0, c);
1183 | else if (n == 2) _ipixel_store_16(lptr, 0, c);
1184 | else if (n == 3) _ipixel_store_24(lptr, 0, c);
1185 | else if (n == 4) _ipixel_store_32(lptr, 0, c);
1186 | }
1187 |
1188 | return (void*)lptr;
1189 | }
1190 |
1191 | //---------------------------------------------------------------------
1192 | // tga - iload_tga_stream
1193 | //---------------------------------------------------------------------
1194 | struct IBITMAP *iload_tga_stream(IMDIO *stream, IRGB *pal)
1195 | {
1196 | unsigned char image_palette[256][3];
1197 | unsigned char id_length, palette_type, image_type, palette_entry_size;
1198 | unsigned char bpp, descriptor_bits;
1199 | IUINT32 c, i, y, yc, n, x;
1200 | IUINT16 palette_colors;
1201 | IUINT16 image_width, image_height;
1202 | unsigned char *lptr;
1203 | struct IBITMAP *bmp;
1204 | int compressed, want_palette, count;
1205 | IRGB tmppal[256];
1206 |
1207 | assert(stream);
1208 |
1209 | _is_perrno_set(0);
1210 |
1211 | want_palette = 1;
1212 | if (!pal) {
1213 | want_palette = 0;
1214 | pal = tmppal;
1215 | }
1216 |
1217 | id_length = is_getc(stream);
1218 | palette_type = is_getc(stream);
1219 | image_type = is_getc(stream);
1220 | is_igetw(stream);
1221 | palette_colors = is_igetw(stream);
1222 | palette_entry_size = is_getc(stream);
1223 | is_igetw(stream);
1224 | is_igetw(stream);
1225 | image_width = is_igetw(stream);
1226 | image_height = is_igetw(stream);
1227 | bpp = is_getc(stream);
1228 | descriptor_bits = is_getc(stream);
1229 |
1230 | is_seekcur(stream, id_length);
1231 |
1232 | if (palette_type == 1) {
1233 | for (i = 0; i < (IUINT32)palette_colors; i++) {
1234 | if (palette_entry_size == 16) {
1235 | c = is_igetw(stream);
1236 | image_palette[i][0] = (IUINT8)_ipixel_scale_5[(c >> 0) & 31];
1237 | image_palette[i][1] = (IUINT8)_ipixel_scale_5[(c >> 5) & 31];
1238 | image_palette[i][2] = (IUINT8)_ipixel_scale_5[(c >> 10) & 31];
1239 | }
1240 | else if (palette_entry_size >= 24) {
1241 | image_palette[i][0] = is_getc(stream);
1242 | image_palette[i][1] = is_getc(stream);
1243 | image_palette[i][2] = is_getc(stream);
1244 | if (palette_entry_size == 32) is_getc(stream);
1245 |
1246 | }
1247 | }
1248 | }
1249 | else if (palette_type != 0) {
1250 | _is_perrno_set(1);
1251 | return NULL;
1252 | }
1253 |
1254 | /*
1255 | * (image_type & 7): 1/colormapped, 2/truecolor, 3/grayscale
1256 | * (image_type & 8): 0/uncompressed, 8/compressed
1257 | */
1258 | compressed = (image_type & 8);
1259 | image_type = (image_type & 7);
1260 |
1261 | if ((image_type < 1) || (image_type > 3)) {
1262 | _is_perrno_set(2);
1263 | return NULL;
1264 | }
1265 |
1266 | if (image_type == 1) { /* paletted image */
1267 | if ((palette_type != 1) || (bpp != 8)) {
1268 | _is_perrno_set(11);
1269 | return NULL;
1270 | }
1271 | for(i = 0; i < (IUINT32)palette_colors; i++) {
1272 | pal[i].r = image_palette[i][2];
1273 | pal[i].g = image_palette[i][1];
1274 | pal[i].b = image_palette[i][0];
1275 | }
1276 | }
1277 | else if (image_type == 2) { /* truecolor image */
1278 | if (palette_type != 0) {
1279 | _is_perrno_set(21);
1280 | return NULL;
1281 | }
1282 | if (bpp != 15 && bpp != 16 && bpp != 24 && bpp != 32) {
1283 | _is_perrno_set(22);
1284 | return NULL;
1285 | }
1286 | if (bpp == 16) bpp = 15;
1287 | }
1288 | else if (image_type == 3) { /* grayscale image */
1289 | if ((palette_type != 0) || (bpp != 8)) {
1290 | _is_perrno_set(31);
1291 | return NULL;
1292 | }
1293 | for (i = 0; i < 256; i++) {
1294 | pal[i].r = (unsigned char)(i);
1295 | pal[i].g = (unsigned char)(i);
1296 | pal[i].b = (unsigned char)(i);
1297 | }
1298 | }
1299 |
1300 | n = (bpp + 7) >> 3;
1301 | bmp = ibitmap_create(image_width, image_height, bpp);
1302 | if (!bmp) {
1303 | _is_perrno_set(50);
1304 | return NULL;
1305 | }
1306 | for (y = 0; y < bmp->h; y++) {
1307 | memset(bmp->line[y], 0, bmp->pitch);
1308 | }
1309 |
1310 | for (y = image_height; y; y--) {
1311 | yc = (descriptor_bits & 0x20) ? image_height - y : y - 1;
1312 | lptr = (unsigned char*)(bmp->line[yc]);
1313 | if (compressed == 0) {
1314 | raw_tga_readn(lptr, image_width, bpp, stream);
1315 | } else {
1316 | for (x = 0; x < (IUINT32)image_width; x += count) {
1317 | count = is_getc(stream);
1318 | if (count & 0x80) {
1319 | count = (count & 0x7F) + 1;
1320 | c = single_tga_readn(stream, bpp);
1321 | for (i = 0; i < (IUINT32)count; i++, lptr += n) {
1322 | if (n == 1) _ipixel_store_8(lptr, 0, c);
1323 | else if (n == 2) _ipixel_store_16(lptr, 0, c);
1324 | else if (n == 3) _ipixel_store_24(lptr, 0, c);
1325 | else if (n == 4) _ipixel_store_32(lptr, 0, c);
1326 | }
1327 | } else {
1328 | count = count + 1;
1329 | raw_tga_readn(lptr, count, bpp, stream);
1330 | lptr = lptr + n * count;
1331 | }
1332 | }
1333 | }
1334 | }
1335 |
1336 | if (_is_perrno_get()) {
1337 | ibitmap_release(bmp);
1338 | return NULL;
1339 | }
1340 |
1341 | ibitmap_pixfmt_set(bmp, ibitmap_pixfmt_guess(bmp));
1342 |
1343 | /* construct a fake palette if 8-bit mode is not involved */
1344 | if ((bpp != 8) && want_palette) {
1345 | // _igenerate_332_palette(pal);
1346 | }
1347 |
1348 | return bmp;
1349 | }
1350 |
1351 | //---------------------------------------------------------------------
1352 | // tga - isave_tga_stream
1353 | //---------------------------------------------------------------------
1354 | int isave_tga_stream(IMDIO *stream, struct IBITMAP *bmp, const IRGB *pal)
1355 | {
1356 | unsigned char image_palette[256][3];
1357 | IUINT32 c, a, r, g, b, p;
1358 | long x, y, depth, n;
1359 | IRGB tmppal[256];
1360 | int fmt;
1361 |
1362 | assert(bmp);
1363 | assert(stream);
1364 |
1365 | if (!pal) {
1366 | memcpy(tmppal, _ipaletted, 256 * sizeof(IRGB));
1367 | pal = tmppal;
1368 | }
1369 |
1370 | depth = bmp->bpp;
1371 |
1372 | if (depth == 15) depth = 16;
1373 | _is_perrno_set(0);
1374 |
1375 | is_putc(stream, 0); /* id length (no id saved) */
1376 | is_putc(stream, (depth == 8) ? 1 : 0); /* palette type */
1377 | is_putc(stream, (depth == 8) ? 1 : 2); /* image type */
1378 | is_iputw(stream, 0); /* first colour */
1379 | is_iputw(stream, (depth == 8) ? 256 : 0); /* number of colours */
1380 | is_putc(stream, (depth == 8) ? 24 : 0); /* palette entry size */
1381 | is_iputw(stream, 0); /* left */
1382 | is_iputw(stream, 0); /* top */
1383 | is_iputw(stream, (int)bmp->w); /* width */
1384 | is_iputw(stream, (int)bmp->h); /* height */
1385 | is_putc(stream, depth); /* bits per pixel */
1386 | is_putc(stream, (depth == 32) ? 8 : 0); /* descriptor
1387 | (bottom to top, 8-bit alpha) */
1388 |
1389 | if (depth == 8) {
1390 | for (y = 0; y < 256; y++) {
1391 | image_palette[y][2] = pal[y].r;
1392 | image_palette[y][1] = pal[y].g;
1393 | image_palette[y][0] = pal[y].b;
1394 | is_putc(stream, image_palette[y][0]);
1395 | is_putc(stream, image_palette[y][1]);
1396 | is_putc(stream, image_palette[y][2]);
1397 | }
1398 | }
1399 |
1400 | n = (bmp->bpp + 7) / 8;
1401 |
1402 | fmt = _ibitmap_guess_pixfmt(bmp);
1403 |
1404 | for (y = (long)bmp->h - 1; y >= 0; y--) {
1405 | for (x = 0; x < (long)bmp->w; x++) {
1406 | c = _is_getpx(bmp, x, y);
1407 | p = _im_color_get(fmt, c, pal);
1408 | a = (p >> 24) & 0xFF;
1409 | r = (p >> 16) & 0xFF;
1410 | g = (p >> 8) & 0xFF;
1411 | b = (p >> 0) & 0xFF;
1412 | if (n == 1) is_putc(stream, c);
1413 | else if (n == 2) {
1414 | c = ((r << 7) & 0x7C00) | ((g << 2) & 0x3E0);
1415 | is_iputw(stream, c | ((b >> 3) & 0x1F));
1416 | }
1417 | else if (n == 3 || n == 4) {
1418 | is_putc(stream, b);
1419 | is_putc(stream, g);
1420 | is_putc(stream, r);
1421 | if (n == 4) is_putc(stream, a);
1422 | }
1423 | }
1424 | }
1425 |
1426 | return 0;
1427 | }
1428 |
1429 | //---------------------------------------------------------------------
1430 | // tga - isave_tga_file
1431 | //---------------------------------------------------------------------
1432 | int isave_tga_file(const char *file, struct IBITMAP *bmp, const IRGB *pal)
1433 | {
1434 | IMDIO stream;
1435 | int retval;
1436 |
1437 | if (is_open_file(&stream, file, "wb")) return -1;
1438 | retval = isave_tga_stream(&stream, bmp, pal);
1439 | is_close_file(&stream);
1440 |
1441 | return retval;
1442 | }
1443 |
1444 | //---------------------------------------------------------------------
1445 | // Loader Definition:
1446 | // Add new loader to load other picture formats
1447 | //---------------------------------------------------------------------
1448 | static IPICLOADER iloader_table[256];
1449 |
1450 | void iloader_table_init(void)
1451 | {
1452 | static int inited = 0;
1453 | int i;
1454 | if (inited) return;
1455 | for (i = 0; i < 256; i++) iloader_table[i] = NULL;
1456 | inited = 1;
1457 | }
1458 |
1459 |
1460 | //---------------------------------------------------------------------
1461 | // setup a new loader:
1462 | // using First Byte of the Picture to choose loader for different formats
1463 | // NULL for disable the loader
1464 | //---------------------------------------------------------------------
1465 | IPICLOADER ipic_loader(unsigned char firstbyte, IPICLOADER loader)
1466 | {
1467 | IPICLOADER oldloader;
1468 | iloader_table_init();
1469 | oldloader = iloader_table[firstbyte];
1470 | iloader_table[firstbyte] = loader;
1471 | return oldloader;
1472 | }
1473 |
1474 | //---------------------------------------------------------------------
1475 | // recognize data stream and load picture
1476 | //---------------------------------------------------------------------
1477 | struct IBITMAP *iload_picture(IMDIO *stream, IRGB *pal)
1478 | {
1479 | unsigned char firstbyte;
1480 | int ch;
1481 |
1482 | assert(stream);
1483 |
1484 | iloader_table_init();
1485 |
1486 | ch = is_getc(stream);
1487 | if (ch < 0) return NULL;
1488 | is_ungetc(stream, ch);
1489 |
1490 | firstbyte = (unsigned char)(ch & 0xff);
1491 | if (iloader_table[firstbyte] != NULL) {
1492 | return iloader_table[firstbyte](stream, pal);
1493 | }
1494 |
1495 | if (ch == 'B') {
1496 | return iload_bmp_stream(stream, pal);
1497 | } else
1498 | if (ch == 'G') {
1499 | return iload_gif_stream(stream, pal);
1500 | }
1501 | return iload_tga_stream(stream, pal);
1502 | }
1503 |
1504 |
1505 | //=====================================================================
1506 | // ORIGINAL OPERATION
1507 | //=====================================================================
1508 | static IRGB _idefault_pal[256];
1509 |
1510 | void ipic_read_pal(void *_pal)
1511 | {
1512 | memcpy(_pal, _idefault_pal, 256 * 4);
1513 | }
1514 |
1515 | void ipic_write_pal(const void *_pal)
1516 | {
1517 | memcpy(_idefault_pal, _pal, 256 * 4);
1518 | }
1519 |
1520 | struct IBITMAP *ipic_convert(struct IBITMAP *src, int dfmt, const IRGB *pal)
1521 | {
1522 | struct IBITMAP *bmp;
1523 | int sfmt;
1524 | int w, h;
1525 | w = (int)src->w;
1526 | h = (int)src->h;
1527 | sfmt = _ibitmap_guess_pixfmt(src);
1528 | if (sfmt == dfmt) {
1529 | bmp = ibitmap_create(w, h, src->bpp);
1530 | if (bmp == NULL) return NULL;
1531 | ibitmap_blit(bmp, 0, 0, src, 0, 0, w, h, 0);
1532 | return bmp;
1533 | }
1534 | bmp = ibitmap_convfmt(dfmt, src, pal, pal);
1535 | return bmp;
1536 | }
1537 |
1538 | struct IBITMAP *ipic_load_file(const char *file, long pos, IRGB *pal)
1539 | {
1540 | IMDIO stream;
1541 | struct IBITMAP *bmp;
1542 | IRGB *p = pal == NULL? _ipaletted : pal;
1543 |
1544 | if (is_open_file(&stream, file, "rb")) {
1545 | _is_perrno_set(-1);
1546 | return NULL;
1547 | }
1548 | fseek((FILE*)(stream.data), pos, SEEK_SET);
1549 | bmp = iload_picture(&stream, p);
1550 | is_close_file(&stream);
1551 |
1552 | return bmp;
1553 | }
1554 |
1555 | struct IBITMAP *ipic_load_mem(const void *ptr, long size, IRGB *pal)
1556 | {
1557 | IMDIO stream;
1558 | struct IBITMAP *bmp;
1559 | IRGB *p = pal == NULL ? _ipaletted : pal;
1560 | size = (size <= 0)? 0x7fffffffl : size;
1561 | is_init_mem(&stream, ptr, size);
1562 | bmp = iload_picture(&stream, p);
1563 | return bmp;
1564 | }
1565 |
1566 |
1567 | //=====================================================================
1568 | //
1569 | // GIF Operation Interface
1570 | // Since lzw's patent has expired, we can decode/encode gif freely
1571 | //
1572 | //=====================================================================
1573 |
1574 | //---------------------------------------------------------------------
1575 | // _igif_clear_table - clear lzw table
1576 | //---------------------------------------------------------------------
1577 | static void _igif_clear_table(IGIFDESC *gif)
1578 | {
1579 | gif->empty_string = gif->cc + 2;
1580 | gif->curr_bit_size = gif->bit_size + 1;
1581 | gif->bit_overflow = 0;
1582 | }
1583 |
1584 | //---------------------------------------------------------------------
1585 | // _igif_get_code - get input code with current bit size
1586 | //---------------------------------------------------------------------
1587 | static void _igif_get_code(IGIFDESC *gif)
1588 | {
1589 | if (gif->bit_pos + gif->curr_bit_size > 8) {
1590 | if (gif->data_pos >= gif->data_len) {
1591 | gif->data_len = is_getc(gif->stream);
1592 | gif->data_pos = 0;
1593 | }
1594 | gif->entire = (is_getc(gif->stream) << 8) + gif->entire;
1595 | gif->data_pos++;
1596 | }
1597 | if (gif->bit_pos + gif->curr_bit_size > 16) {
1598 | if (gif->data_pos >= gif->data_len) {
1599 | gif->data_len = is_getc(gif->stream);
1600 | gif->data_pos = 0;
1601 | }
1602 | gif->entire = (is_getc(gif->stream) << 16) + gif->entire;
1603 | gif->data_pos++;
1604 | }
1605 | gif->code = (gif->entire >> gif->bit_pos) & ((1 <<
1606 | gif->curr_bit_size) - 1);
1607 | if (gif->bit_pos + gif->curr_bit_size > 8)
1608 | gif->entire >>= 8;
1609 | if (gif->bit_pos + gif->curr_bit_size > 16)
1610 | gif->entire >>= 8;
1611 | gif->bit_pos = (gif->bit_pos + gif->curr_bit_size) % 8;
1612 | if (gif->bit_pos == 0) {
1613 | if (gif->data_pos >= gif->data_len) {
1614 | gif->data_len = is_getc(gif->stream);
1615 | gif->data_pos = 0;
1616 | }
1617 | gif->entire = is_getc(gif->stream);
1618 | gif->data_pos++;
1619 | }
1620 | }
1621 |
1622 | //---------------------------------------------------------------------
1623 | // _igif_get_string - get string into gif->string
1624 | //---------------------------------------------------------------------
1625 | static void _igif_get_string(IGIFDESC *gif, int num)
1626 | {
1627 | unsigned char *string;
1628 | int i;
1629 | string = gif->string;
1630 | if (num < gif->cc) {
1631 | gif->string_length = 1;
1632 | string[0] = gif->newc[num];
1633 | } else {
1634 | i = gif->str[num].length;
1635 | gif->string_length = i;
1636 | for (; i > 0; ) {
1637 | i--;
1638 | string[i] = gif->newc[num];
1639 | num = gif->str[num].base;
1640 | }
1641 | }
1642 | }
1643 |
1644 | //---------------------------------------------------------------------
1645 | // _igif_output_string - output string to bitmap
1646 | //---------------------------------------------------------------------
1647 | static void _igif_output_string(IGIFDESC *gif)
1648 | {
1649 | unsigned char *string, **line, *ptr, mask;
1650 | int imgx, imgy, x, y, len, last, i;
1651 | if (gif->error || gif->bitmap == NULL) return;
1652 | x = gif->x;
1653 | y = gif->y;
1654 | imgx = gif->image_x;
1655 | imgy = gif->image_y;
1656 | line = (unsigned char**)gif->bitmap->line;
1657 | string = gif->string;
1658 | last = gif->string_length;
1659 | for (; last > 0; ) {
1660 | len = gif->image_w + imgx - x;
1661 | len = len > last ? last : len;
1662 | if (gif->transparent < 0) {
1663 | memcpy(line[y] + x, string, len);
1664 | x += len;
1665 | string += len;
1666 | } else {
1667 | mask = (unsigned char)gif->transparent;
1668 | ptr = line[y] + x;
1669 | for (i = len; i > 0; i--) {
1670 | if (string[0] != mask) *ptr = *string;
1671 | string++;
1672 | ptr++;
1673 | }
1674 | x += len;
1675 | }
1676 | last -= len;
1677 | if (x >= imgx + gif->image_w) {
1678 | x = imgx;
1679 | y += gif->interlace;
1680 | if (gif->interlace) {
1681 | if (y >= imgy + gif->image_h) {
1682 | if (gif->interlace == 8 && (y - imgy) % 8 == 0) {
1683 | gif->interlace = 8;
1684 | y = imgy + 4;
1685 | } else
1686 | if (gif->interlace == 8 && (y - imgy) % 8 == 4) {
1687 | gif->interlace = 4;
1688 | y = imgy + 2;
1689 | } else
1690 | if (gif->interlace == 4) {
1691 | gif->interlace = 2;
1692 | y = imgy + 1;
1693 | }
1694 | }
1695 | }
1696 | }
1697 | }
1698 | gif->x = x;
1699 | gif->y = y;
1700 | }
1701 |
1702 | //---------------------------------------------------------------------
1703 | // ipic_gif_open - open gif and load header
1704 | //---------------------------------------------------------------------
1705 | int ipic_gif_open(IGIFDESC *gif, IMDIO *stream, IRGB *pal, int customer)
1706 | {
1707 | long c, i;
1708 |
1709 | assert(gif && stream);
1710 | memset(gif, 0, sizeof(IGIFDESC));
1711 |
1712 | gif->stream = stream;
1713 |
1714 | c = is_mgetw(stream) << 8;
1715 | c = c | is_getc(stream);
1716 | gif->state = -1;
1717 | if (c != 0x474946) {
1718 | return -1;
1719 | }
1720 |
1721 | is_seekcur(stream, 3);
1722 |
1723 | gif->width = is_igetw(stream);
1724 | gif->height = is_igetw(stream);
1725 | gif->flags = 0;
1726 | gif->delay = 0;
1727 | gif->hotx = 0;
1728 | gif->hoty = 0;
1729 | gif->frame = -1;
1730 |
1731 | gif->pal = pal;
1732 | gif->bpp = 0;
1733 |
1734 | c = is_getc(stream);
1735 | if (c & 128)
1736 | gif->bpp = (c & 7) + 1;
1737 |
1738 | gif->background = (unsigned char)is_getc(stream);
1739 | gif->aspect = (unsigned char)is_getc(stream);
1740 |
1741 | if (gif->bpp && pal) {
1742 | for (i = 0; i < (1 << gif->bpp); i++) {
1743 | pal[i].r = is_getc(stream);
1744 | pal[i].g = is_getc(stream);
1745 | pal[i].b = is_getc(stream);
1746 | }
1747 | }
1748 | else if (gif->bpp) {
1749 | is_seekcur(stream, (1 << gif->bpp) * 3);
1750 | }
1751 |
1752 | if (customer == 0) {
1753 | gif->bitmap = ibitmap_create(gif->width, gif->height * 2, 8);
1754 | if (gif->bitmap == NULL) {
1755 | return -2;
1756 | }
1757 | ibitmap_fill(gif->bitmap, 0, 0, gif->width, gif->height * 2,
1758 | gif->background, 0);
1759 | ibitmap_pixfmt_set(gif->bitmap, IPIX_FMT_C8);
1760 | }
1761 |
1762 | gif->state = 1;
1763 | gif->error = 0;
1764 | gif->transparent = -1;
1765 | gif->flags = customer? IGIF_CUSTOMERBMP : 0;
1766 |
1767 | return 0;
1768 | }
1769 |
1770 | //---------------------------------------------------------------------
1771 | // ipic_gif_close - close gif and free bitmap
1772 | //---------------------------------------------------------------------
1773 | int ipic_gif_close(IGIFDESC *gif)
1774 | {
1775 | if ((gif->flags & IGIF_CUSTOMERBMP) == 0) {
1776 | ibitmap_release(gif->bitmap);
1777 | gif->bitmap = NULL;
1778 | }
1779 | if (gif->state == 2 || gif->state == 3) {
1780 | is_putc(gif->stream, 0x3b);
1781 | }
1782 | gif->state = 0;
1783 | return 0;
1784 | }
1785 |
1786 | //---------------------------------------------------------------------
1787 | // ipic_gif_read_image_desc - read image desc
1788 | //---------------------------------------------------------------------
1789 | static int ipic_gif_read_image_desc(IGIFDESC *gif)
1790 | {
1791 | unsigned char *string;
1792 | IMDIO *stream;
1793 | int dispose, depth, old, i;
1794 | int retval = 0;
1795 |
1796 | if (gif->state != 1) return -1;
1797 | stream = gif->stream;
1798 | string = gif->string;
1799 |
1800 | gif->image_x = is_igetw(stream);
1801 | gif->image_y = is_igetw(stream);
1802 | gif->image_w = is_igetw(stream);
1803 | gif->image_h = is_igetw(stream);
1804 |
1805 | ibitmap_blit(gif->bitmap, gif->image_x, gif->image_y, gif->bitmap,
1806 | gif->image_x, gif->image_y + gif->height, gif->image_w,
1807 | gif->image_h, 0);
1808 |
1809 | if (gif->image_x < 0 || gif->image_y < 0 ||
1810 | gif->image_x + gif->image_w > gif->width ||
1811 | gif->image_y + gif->image_h > gif->height)
1812 | gif->error = 1;
1813 |
1814 | i = is_getc(stream);
1815 | if (i & 64) gif->interlace = 8;
1816 | else gif->interlace = 1;
1817 |
1818 | if (i & 128) {
1819 | depth = (i & 7) + 1;
1820 | if (gif->pal) {
1821 | for (i = 0; i < (1 << depth); i++) {
1822 | gif->pal[i].r = is_getc(stream);
1823 | gif->pal[i].g = is_getc(stream);
1824 | gif->pal[i].b = is_getc(stream);
1825 | }
1826 | } else {
1827 | is_seekcur(stream, (1 << depth) * 3);
1828 | }
1829 | }
1830 |
1831 | gif->bit_size = is_getc(stream);
1832 | gif->cc = 1 << gif->bit_size;
1833 |
1834 | for (i = 0; i < gif->cc; i++) {
1835 | gif->str[i].base = -1;
1836 | gif->str[i].length = 1;
1837 | gif->newc[i] = (unsigned char)i;
1838 | }
1839 |
1840 | gif->bit_pos = 0;
1841 | gif->data_len = is_getc(stream);
1842 | gif->data_pos = 0;
1843 | gif->entire = is_getc(stream);
1844 | gif->data_pos++;
1845 | gif->string_length = 0;
1846 | gif->x = gif->image_x;
1847 | gif->y = gif->image_y;
1848 |
1849 | _igif_clear_table(gif);
1850 | _igif_get_code(gif);
1851 | if (gif->code == gif->cc)
1852 | _igif_get_code(gif);
1853 |
1854 | _igif_get_string(gif, gif->code);
1855 | _igif_output_string(gif);
1856 | old = gif->code;
1857 |
1858 | for (; ; ) {
1859 | _igif_get_code(gif);
1860 | if (gif->code == gif->cc + 1) {
1861 | break;
1862 | }
1863 | if (gif->entire < 0) {
1864 | retval = -1;
1865 | gif->error = 2;
1866 | break;
1867 | }
1868 | if (gif->code == gif->cc) {
1869 | _igif_clear_table(gif);
1870 | _igif_get_code(gif);
1871 | _igif_get_string(gif, gif->code);
1872 | _igif_output_string(gif);
1873 | old = gif->code;
1874 | } else
1875 | if (gif->code < gif->empty_string) {
1876 | _igif_get_string(gif, gif->code);
1877 | _igif_output_string(gif);
1878 | if (gif->bit_overflow == 0) {
1879 | i = gif->empty_string;
1880 | gif->str[i].base = (short)old;
1881 | gif->str[i].length = gif->str[old].length + 1;
1882 | gif->newc[i] = string[0];
1883 | gif->empty_string++;
1884 | if (gif->empty_string == (1 << gif->curr_bit_size))
1885 | gif->curr_bit_size++;
1886 | if (gif->curr_bit_size == 13) {
1887 | gif->curr_bit_size = 12;
1888 | gif->bit_overflow = 1;
1889 | }
1890 | }
1891 | old = gif->code;
1892 | } else {
1893 | _igif_get_string(gif, old);
1894 | string[gif->str[old].length] = string[0];
1895 | gif->string_length++;
1896 | if (gif->bit_overflow == 0) {
1897 | i = gif->empty_string;
1898 | gif->str[i].base = (short)old;
1899 | gif->str[i].length = gif->str[old].length + 1;
1900 | gif->newc[i] = string[0];
1901 | gif->empty_string++;
1902 | if (gif->empty_string == (1 << gif->curr_bit_size))
1903 | gif->curr_bit_size++;
1904 | if (gif->curr_bit_size == 13) {
1905 | gif->curr_bit_size = 12;
1906 | gif->bit_overflow = 1;
1907 | }
1908 | }
1909 | _igif_output_string(gif);
1910 | old = gif->code;
1911 | }
1912 | }
1913 |
1914 | dispose = (gif->method >> 2) & 7;
1915 | if (dispose == 2) {
1916 | i = gif->transparent >= 0? gif->transparent : gif->background;
1917 | ibitmap_fill(gif->bitmap, gif->image_x, gif->image_y + gif->height,
1918 | gif->image_w, gif->image_h, i, 0);
1919 | } else
1920 | if (dispose != 3) {
1921 | ibitmap_blit(gif->bitmap, gif->image_x, gif->image_y + gif->height,
1922 | gif->bitmap, gif->image_x, gif->image_y,
1923 | gif->image_w, gif->image_h, 0);
1924 | }
1925 |
1926 | gif->frame++;
1927 |
1928 | return retval;
1929 | }
1930 |
1931 | //---------------------------------------------------------------------
1932 | // ipic_gif_read_extension - read extension
1933 | //---------------------------------------------------------------------
1934 | int ipic_gif_read_extension(IGIFDESC *gif, int firstcmd)
1935 | {
1936 | IMDIO *stream;
1937 | int control, c;
1938 | char ident[12];
1939 |
1940 | stream = gif->stream;
1941 | gif->delay = 0;
1942 | gif->transparent = -1;
1943 | gif->method = 0;
1944 |
1945 | if (firstcmd < 0) control = is_getc(stream);
1946 | else control = firstcmd;
1947 |
1948 | if (control == 0xf9) {
1949 | c = is_getc(stream);
1950 | if (c != 4) return -1;
1951 |
1952 | gif->method = is_getc(stream);
1953 | gif->delay = is_igetw(stream);
1954 |
1955 | gif->transparent = is_getc(stream);
1956 | gif->bitmap->mask = (unsigned char)gif->transparent;
1957 |
1958 | if ((gif->method & 1) == 0)
1959 | gif->transparent = -1;
1960 |
1961 | c = (gif->method >> 2) & 7;
1962 |
1963 | if (c == 20) {
1964 | }
1965 | } else
1966 | if (control == 0xff) {
1967 | c = is_getc(stream);
1968 | if (c == 0x0b) {
1969 | is_reader(stream, ident, 0x0b);
1970 | if (memcmp(ident, "PIXIAGIF.CH", 0x0b) == 0) {
1971 | c = is_getc(stream);
1972 | if (c == 5) {
1973 | c = is_getc(stream);
1974 | gif->flags = (gif->flags & ~0xff) | (c & 0xff);
1975 | gif->hotx = (short)is_igetw(stream);
1976 | gif->hoty = (short)is_igetw(stream);
1977 | } else {
1978 | is_ungetc(stream, c);
1979 | }
1980 | }
1981 | } else {
1982 | is_ungetc(stream, c);
1983 | }
1984 | }
1985 |
1986 | for (; ; ) {
1987 | c = is_getc(stream);
1988 | if (c <= 0) break;
1989 | is_seekcur(stream, c);
1990 | }
1991 |
1992 | return 0;
1993 | }
1994 |
1995 | //---------------------------------------------------------------------
1996 | // ipic_gif_read_frame - read single frame
1997 | //---------------------------------------------------------------------
1998 | int ipic_gif_read_frame(IGIFDESC *gif)
1999 | {
2000 | int retval, type;
2001 | if (gif->state != 1) return -1;
2002 |
2003 | for (retval = 0; gif->error == 0; ) {
2004 | type = is_getc(gif->stream);
2005 | if (type < 0 || type == 0x3b || gif->error) {
2006 | retval = -2;
2007 | break;
2008 | }
2009 | if (type == 0) continue;
2010 | switch (type)
2011 | {
2012 | case 0x21:
2013 | ipic_gif_read_extension(gif, -1);
2014 | break;
2015 | case 0x2c:
2016 | ipic_gif_read_image_desc(gif);
2017 | type = 0;
2018 | break;
2019 | case 0x01:
2020 | case 0xf9:
2021 | case 0xfe:
2022 | case 0xff:
2023 | ipic_gif_read_extension(gif, type);
2024 | break;
2025 | default:
2026 | //printf("gif unknow %d\n", type);
2027 | retval = -3;
2028 | gif->error = 5;
2029 | break;
2030 | }
2031 | if (type == 0) break;
2032 | }
2033 | return retval;
2034 | }
2035 |
2036 | //---------------------------------------------------------------------
2037 | // load gif picture from stream
2038 | //---------------------------------------------------------------------
2039 | struct IBITMAP *iload_gif_stream(IMDIO *stream, IRGB *pal)
2040 | {
2041 | struct IBITMAP *bmp;
2042 | IGIFDESC *gif;
2043 | gif = (IGIFDESC*)malloc(sizeof(IGIFDESC));
2044 | if (gif == NULL) return NULL;
2045 | if (ipic_gif_open(gif, stream, pal, 0) != 0) {
2046 | free(gif);
2047 | return NULL;
2048 | }
2049 | for (; ; ) {
2050 | if (ipic_gif_read_frame(gif) < 0) break;
2051 | }
2052 | bmp = ibitmap_create(gif->width, gif->height, 8);
2053 | if (bmp == NULL) {
2054 | ibitmap_release(gif->bitmap);
2055 | free(gif);
2056 | return NULL;
2057 | }
2058 | ibitmap_blit(bmp, 0, 0, gif->bitmap, 0, 0, gif->width,
2059 | gif->height, 0);
2060 | bmp->mask = (gif->transparent & 0xffff) | ((gif->flags & 0xffff) << 16);
2061 | bmp->mode = (gif->hotx << 16) | (gif->hoty & 0xffff);
2062 | ibitmap_release(gif->bitmap);
2063 | free(gif);
2064 | return bmp;
2065 | }
2066 |
2067 | //---------------------------------------------------------------------
2068 | // open gif stream for saving
2069 | //---------------------------------------------------------------------
2070 | int ipic_gif_wopen(IGIFDESC *gif, IMDIO *stream, const IRGB *pal,
2071 | int w, int h, int background, int aspect, int flags, long hotxy)
2072 | {
2073 | int i;
2074 |
2075 | assert(gif && stream);
2076 | memset(gif, 0, sizeof(IGIFDESC));
2077 |
2078 | pal = pal ? pal : (const IRGB*)_ipaletted;
2079 |
2080 | gif->stream = stream;
2081 | gif->pal = (IRGB*)pal;
2082 | gif->width = w;
2083 | gif->height = h;
2084 | gif->bpp = 8;
2085 | gif->background = background;
2086 | gif->aspect = aspect <= 0 ? 0 : aspect;
2087 |
2088 | gif->image_x = 0;
2089 | gif->image_y = 0;
2090 | gif->image_w = w;
2091 | gif->image_h = h;
2092 | gif->interlace = 1;
2093 | gif->flags = flags;
2094 | gif->x = 0;
2095 | gif->y = 0;
2096 | gif->hotx = (short)((hotxy >> 16) & 0xffff);
2097 | gif->hoty = (short)(hotxy & 0xffff);
2098 |
2099 | if ((gif->flags & IGIF_CUSTOMERBMP) == 0) {
2100 | gif->bitmap = ibitmap_create(gif->width, gif->height * 2, 8);
2101 | if (gif->bitmap == NULL) {
2102 | return -1;
2103 | }
2104 | ibitmap_fill(gif->bitmap, 0, 0, gif->width, gif->height * 2,
2105 | gif->background, 0);
2106 | }
2107 |
2108 | if (gif->flags & 0xff) flags |= IGIF_ANIMATE;
2109 |
2110 | is_writer(stream, "GIF", 3);
2111 | is_writer(stream, (flags & IGIF_ANIMATE) ? "89a" : "87a", 3);
2112 | is_iputw(stream, gif->width);
2113 | is_iputw(stream, gif->height);
2114 | is_putc(stream, 0xf7);
2115 | is_putc(stream, gif->background);
2116 | is_putc(stream, gif->aspect);
2117 |
2118 | for (i = 0; i < 256; i++) {
2119 | is_putc(stream, pal[i].r);
2120 | is_putc(stream, pal[i].g);
2121 | is_putc(stream, pal[i].b);
2122 | }
2123 |
2124 | gif->transparent = -1;
2125 | gif->flags = flags;
2126 | gif->error = 0;
2127 | gif->delay = (flags & IGIF_ANIMATE) ? 0 : -1;
2128 | gif->state = (flags & IGIF_ANIMATE) ? 3 : 2;
2129 |
2130 | if (gif->flags & 0xff) {
2131 | is_putc(stream, 0x21);
2132 | is_putc(stream, 0xff);
2133 | is_putc(stream, 0x0b);
2134 | is_writer(stream, "PIXIAGIF.CH", 0x0b);
2135 | is_putc(stream, 5);
2136 | is_putc(stream, gif->flags & 0xff);
2137 | is_iputw(stream, gif->hotx);
2138 | is_iputw(stream, gif->hoty);
2139 | is_putc(stream, 0);
2140 | }
2141 |
2142 | return 0;
2143 | }
2144 |
2145 | //---------------------------------------------------------------------
2146 | // _igif_write_code - write bits into buffer
2147 | //---------------------------------------------------------------------
2148 | static void _igif_write_code(IGIFDESC *gif, int code, int bit_size)
2149 | {
2150 | if (code < 0) {
2151 | gif->entire &= (1 << gif->bit_pos) - 1;
2152 | gif->string[gif->data_len] = (unsigned char)gif->entire;
2153 | gif->entire >>= 8;
2154 | gif->data_len++;
2155 | is_putc(gif->stream, gif->data_len);
2156 | is_writer(gif->stream, gif->string, gif->data_len);
2157 | gif->data_len = 0;
2158 | gif->bit_pos = 0;
2159 | return;
2160 | }
2161 |
2162 | gif->entire |= code << (gif->bit_pos);
2163 | gif->bit_pos += bit_size;
2164 | while (gif->bit_pos >= 8) {
2165 | gif->string[gif->data_len] = (unsigned char)(gif->entire & 255);
2166 | gif->entire >>= 8;
2167 | gif->bit_pos -= 8;
2168 | gif->data_len++;
2169 | if (gif->data_len >= 252) {
2170 | is_putc(gif->stream, gif->data_len);
2171 | is_writer(gif->stream, gif->string, gif->data_len);
2172 | gif->data_len = 0;
2173 | }
2174 | }
2175 | }
2176 |
2177 | //---------------------------------------------------------------------
2178 | // _igif_get_next_color - get next color
2179 | //---------------------------------------------------------------------
2180 | static int _igif_get_next_color(IGIFDESC *gif)
2181 | {
2182 | int x = gif->x;
2183 | int y = gif->y;
2184 | int c;
2185 |
2186 | if (--gif->string_length < 0) return -1;
2187 |
2188 | c = ((unsigned char*)gif->bitmap->line[y])[x];
2189 | if (++x >= gif->image_x + gif->image_w) {
2190 | x = gif->image_x;
2191 | y += gif->interlace;
2192 | if (gif->interlace) {
2193 | if (y >= gif->image_y + gif->image_h) {
2194 | if (gif->interlace == 8 && (y - gif->image_y) % 8 == 0) {
2195 | gif->interlace = 8;
2196 | y = gif->image_y + 4;
2197 | } else
2198 | if (gif->interlace == 8 && (y - gif->image_y) % 8 == 4) {
2199 | gif->interlace = 4;
2200 | y = gif->image_y + 2;
2201 | } else
2202 | if (gif->interlace == 4) {
2203 | gif->interlace = 2;
2204 | y = gif->image_y + 1;
2205 | }
2206 | }
2207 | }
2208 | }
2209 | gif->x = x;
2210 | gif->y = y;
2211 | return c;
2212 | }
2213 |
2214 | //---------------------------------------------------------------------
2215 | // ipic_gif_write_image_desc - encode image desc
2216 | //---------------------------------------------------------------------
2217 | static int ipic_gif_write_image_desc(IGIFDESC *gif, int palsize)
2218 | {
2219 | IMDIO *stream;
2220 | int palshift, mask, c, i, k;
2221 | int string_buffer = 0;
2222 | int color_num;
2223 | int written;
2224 | int hash;
2225 | int length;
2226 | int interlace;
2227 | short *next;
2228 |
2229 | if (gif->state != 2 && gif->state != 3)
2230 | return -1;
2231 |
2232 | stream = gif->stream;
2233 | is_putc(stream, 0x2c);
2234 | is_iputw(stream, gif->image_x);
2235 | is_iputw(stream, gif->image_y);
2236 | is_iputw(stream, gif->image_w);
2237 | is_iputw(stream, gif->image_h);
2238 | gif->x = gif->image_x;
2239 | gif->y = gif->image_y;
2240 |
2241 | palsize = palsize < 0 ? 0 : palsize;
2242 | for (palshift = 0; palshift < 8; palshift++)
2243 | if ((1 << (palshift + 1)) >= palsize) break;
2244 | palsize = palsize == 0 ? 0 : (1 << (palshift + 1));
2245 | if (gif->interlace <= 1) gif->interlace = 1;
2246 | else gif->interlace = 8;
2247 | mask = palsize? 0x80 : 0;
2248 | mask |= gif->interlace == 8 ? 0x40 : 0;
2249 | mask |= palshift & 7;
2250 |
2251 | is_putc(stream, mask);
2252 | if (palsize > 0) {
2253 | if (gif->pal) {
2254 | for (i = 0; i < palsize; i++) {
2255 | is_putc(stream, gif->pal[i].r);
2256 | is_putc(stream, gif->pal[i].g);
2257 | is_putc(stream, gif->pal[i].b);
2258 | }
2259 | } else {
2260 | for (i = 0; i < palsize; i++) {
2261 | is_putc(stream, i);
2262 | is_putc(stream, i);
2263 | is_putc(stream, i);
2264 | }
2265 | }
2266 | }
2267 |
2268 | gif->string_length = gif->image_w * gif->image_h;
2269 | interlace = gif->interlace;
2270 | for (c = 0, k = 0; c >= 0; ) {
2271 | c = _igif_get_next_color(gif);
2272 | if (c > k) k = c;
2273 | }
2274 |
2275 | for (c = 1; c <= 8; c++)
2276 | if ((1 << c) >= k) break;
2277 |
2278 | gif->bit_size = c;
2279 | gif->cc = 1 << gif->bit_size;
2280 | is_putc(stream, gif->bit_size);
2281 |
2282 | for (i = 0; i < gif->cc + 2; i++) {
2283 | gif->str[i].base = -1;
2284 | gif->str[i].length = 1;
2285 | gif->newc[i] = (unsigned char)i;
2286 | }
2287 |
2288 | next = (short*)(gif->string + 2048);
2289 | for (i = 0; i < 1024; i++) next[i] = -1;
2290 |
2291 | gif->bit_pos = 0;
2292 | gif->data_len = 0;
2293 | gif->data_pos = 0;
2294 | gif->string_length = gif->image_w * gif->image_h;
2295 | gif->x = gif->image_x;
2296 | gif->y = gif->image_y;
2297 | gif->interlace = interlace;
2298 |
2299 | #define _igif_write(g, c) _igif_write_code(g, c, g->curr_bit_size)
2300 |
2301 | _igif_clear_table(gif);
2302 | _igif_write(gif, gif->cc);
2303 |
2304 | for (length = 0; ; ) {
2305 |
2306 | c = _igif_get_next_color(gif);
2307 | if (c < 0) break;
2308 | length++;
2309 |
2310 | if (length == 1) {
2311 | string_buffer = c;
2312 | continue;
2313 | }
2314 |
2315 | /* calculate hash entry */
2316 | hash = ((string_buffer << (gif->bit_size - 1)) | c) & 0x3ff;
2317 | length++;
2318 |
2319 | /* alias str[i].length as str[i].next to reduce memory */
2320 | for (i = next[hash]; i >= 0; i = gif->str[i].length) {
2321 | if (gif->str[i].base != string_buffer) continue;
2322 | if (gif->newc[i] == c) break;
2323 | }
2324 |
2325 | if (i >= 0) {
2326 | string_buffer = i;
2327 | written = 0;
2328 | } else {
2329 | _igif_write(gif, string_buffer);
2330 | color_num = gif->empty_string++;
2331 | written = 1;
2332 |
2333 | /* alias str[i].length as str[i].next to reduce memory */
2334 | if (color_num < 4096) {
2335 | gif->str[color_num].base = string_buffer;
2336 | gif->str[color_num].length = next[hash];
2337 | next[hash] = color_num;
2338 | gif->newc[color_num] = c;
2339 | }
2340 |
2341 | string_buffer = c;
2342 | length = 1;
2343 |
2344 | if (color_num >= (1 << gif->curr_bit_size))
2345 | gif->curr_bit_size++;
2346 |
2347 | if (color_num >= 4094) {
2348 | _igif_write(gif, string_buffer);
2349 | _igif_write(gif, gif->cc);
2350 | _igif_clear_table(gif);
2351 | for (i = 0; i < 1024; i++) next[i] = -1;
2352 | length = 0;
2353 | }
2354 | }
2355 | }
2356 |
2357 | _igif_write(gif, string_buffer);
2358 |
2359 | _igif_write(gif, gif->cc + 1);
2360 | _igif_write(gif, -1);
2361 |
2362 | #undef _igif_write
2363 |
2364 | is_putc(stream, 0);
2365 | is_putc(stream, 0);
2366 |
2367 | written = written;
2368 |
2369 | return 0;
2370 | }
2371 |
2372 | //---------------------------------------------------------------------
2373 | // ipic_gif_write_frame - write frame into gif
2374 | //---------------------------------------------------------------------
2375 | int ipic_gif_write_frame(IGIFDESC *gif, int delay, int mask, int palsize)
2376 | {
2377 | IMDIO *stream;
2378 |
2379 | assert(gif);
2380 | stream = gif->stream;
2381 |
2382 | if (gif->flags & IGIF_ANIMATE) {
2383 | delay = delay < 0 ? 0 : delay;
2384 | is_putc(stream, 0x21);
2385 | is_putc(stream, 0xf9);
2386 | is_putc(stream, 0x04);
2387 | is_putc(stream, mask >= 0? 1 : 0);
2388 | is_iputw(stream, delay);
2389 | is_putc(stream, mask & 0xff);
2390 | is_putc(stream, 0x00);
2391 | }
2392 |
2393 | ipic_gif_write_image_desc(gif, palsize);
2394 |
2395 | return 0;
2396 | }
2397 |
2398 | //---------------------------------------------------------------------
2399 | // save gif picture to stream
2400 | //---------------------------------------------------------------------
2401 | int isave_gif_stream(IMDIO *stream, struct IBITMAP *bmp, const IRGB *pal)
2402 | {
2403 | IGIFDESC *gif;
2404 | long flags;
2405 | long hotxy;
2406 |
2407 | assert(stream && bmp);
2408 |
2409 | gif = (IGIFDESC*)malloc(sizeof(IGIFDESC));
2410 | if (gif == NULL) return 0;
2411 |
2412 | flags = (bmp->mask >> 16) & 0xffff;
2413 | hotxy = bmp->mode;
2414 | if (hotxy != 0 || (flags & 0xff)) flags |= IGIF_ANIMATE;
2415 |
2416 | if (ipic_gif_wopen(gif, stream, pal, bmp->w, bmp->h,
2417 | bmp->mask & 0xff, 0, flags, hotxy)) {
2418 | free(gif);
2419 | return -1;
2420 | }
2421 |
2422 | gif->transparent = (short)(bmp->mask & 0xffff);
2423 | /*gif->transparent = -1; */
2424 |
2425 | ibitmap_blit(gif->bitmap, 0, 0, bmp, 0, 0, bmp->w, bmp->h, 0);
2426 | ipic_gif_write_frame(gif, 0, bmp->mask & 0xff, 0);
2427 | ipic_gif_close(gif);
2428 |
2429 | free(gif);
2430 | return 0;
2431 | }
2432 |
2433 | //---------------------------------------------------------------------
2434 | // save gif picture to stream
2435 | //---------------------------------------------------------------------
2436 | int isave_gif_file(const char *file, struct IBITMAP *bmp, const IRGB *pal)
2437 | {
2438 | IMDIO stream;
2439 | if (is_open_file(&stream, file, "wb")) {
2440 | return -1;
2441 | }
2442 | isave_gif_stream(&stream, bmp, pal);
2443 | is_close_file(&stream);
2444 | return 0;
2445 | }
2446 |
2447 |
2448 |
--------------------------------------------------------------------------------
/pixellib/ipicture.h:
--------------------------------------------------------------------------------
1 | //=====================================================================
2 | //
3 | // ipicture.h - general picture file operation
4 | //
5 | // FEATURES:
6 | // * I/O stream support
7 | // * save and load tga/bmp/gif
8 | //
9 | // NOTE:
10 | // require ibitmap.h, ibmbits.h, ibmcols.h
11 | // for more information, please see the readme file
12 | //
13 | //=====================================================================
14 |
15 | #ifndef __I_PICTURE_H__
16 | #define __I_PICTURE_H__
17 |
18 | #include "ibitmap.h"
19 | #include "ibmbits.h"
20 | #include "ibmcols.h"
21 |
22 | #ifdef __cplusplus
23 | extern "C" {
24 | #endif
25 |
26 |
27 | //=====================================================================
28 | //
29 | // PICTURE DATA INTERFACE
30 | //
31 | // IMDIO - Media Data Input/Output Interface
32 | // PIXELS - Pixel Operation for Bitmaps
33 | // FIXUP - Pixel Format Fixing Up Interface
34 | //
35 | //=====================================================================
36 |
37 | //---------------------------------------------------------------------
38 | // Media Data Streaming Input/Output Interface
39 | //---------------------------------------------------------------------
40 | typedef struct IMDIO
41 | {
42 | int (*getc)(struct IMDIO *stream);
43 | int (*putc)(struct IMDIO *stream, int c);
44 | long _code, _pos, _len, _ch, _bitc, _bitd;
45 | long _cnt, _ungetc;
46 | void *data;
47 | } IMDIO;
48 |
49 | int is_getc(IMDIO *stream);
50 | int is_putc(IMDIO *stream, int c);
51 |
52 | int is_ungetc(IMDIO *stream, int c);
53 |
54 | long is_reader(IMDIO *stream, void *buffer, long size);
55 | long is_writer(IMDIO *stream, const void *buffer, long size);
56 |
57 | int is_igetw(IMDIO *stream);
58 | int is_iputw(IMDIO *stream, int w);
59 | long is_igetl(IMDIO *stream);
60 | long is_iputl(IMDIO *stream, long l);
61 |
62 | int is_mgetw(IMDIO *stream);
63 | int is_mputw(IMDIO *stream, int w);
64 | long is_mgetl(IMDIO *stream);
65 | long is_mputl(IMDIO *stream, long l);
66 |
67 | long is_igetbits(IMDIO *stream, int count);
68 | long is_iputbits(IMDIO *stream, long data, int count);
69 | void is_iflushbits(IMDIO *stream, int isflushwrite);
70 |
71 | long is_mgetbits(IMDIO *stream, int count);
72 | long is_mputbits(IMDIO *stream, long data, int count);
73 | void is_mflushbits(IMDIO *stream, int isflushwrite);
74 |
75 | void is_seekcur(IMDIO *stream, long skip);
76 |
77 |
78 | //---------------------------------------------------------------------
79 | // stream operation
80 | //---------------------------------------------------------------------
81 | int is_init_mem(IMDIO *stream, const void *lptr, long size);
82 | int is_open_file(IMDIO *stream, const char *filename, const char *rw);
83 | int is_close_file(IMDIO *stream);
84 |
85 | void _is_perrno_set(long v);
86 | long _is_perrno_get(void);
87 |
88 | void *is_read_marked_block(IMDIO *stream, const unsigned char *mark,
89 | int marksize, size_t *nbytes_readed);
90 |
91 |
92 | //=====================================================================
93 | //
94 | // PICTURE MEDIA OPERATION
95 | //
96 | // BMP - Windows/OS2 IBITMAP Format, load/save supported
97 | // TGA - Tagged Graphics (Truevision Inc) Format, load/save supported
98 | // GIF - Graphics Interchange Format (CompuServe Inc), load supported
99 | //
100 | //=====================================================================
101 |
102 |
103 | //---------------------------------------------------------------------
104 | // Picture Loading / Saving - Original Interface
105 | //---------------------------------------------------------------------
106 | // load bmp picture from stream
107 | struct IBITMAP *iload_bmp_stream(IMDIO *stream, IRGB *pal);
108 |
109 | // load bmp picture from stream
110 | struct IBITMAP *iload_tga_stream(IMDIO *stream, IRGB *pal);
111 |
112 | // load single gif frame from stream
113 | struct IBITMAP *iload_gif_stream(IMDIO *stream, IRGB *pal);
114 |
115 | // save bmp picture to stream
116 | int isave_bmp_stream(IMDIO *stream, struct IBITMAP *bmp, const IRGB *pal);
117 |
118 | // save tga picture to stream
119 | int isave_tga_stream(IMDIO *stream, struct IBITMAP *bmp, const IRGB *pal);
120 |
121 | // save gif picture to stream
122 | int isave_gif_stream(IMDIO *stream, struct IBITMAP *bmp, const IRGB *pal);
123 |
124 |
125 |
126 | //---------------------------------------------------------------------
127 | // Picture Loading With Format Detecting
128 | //---------------------------------------------------------------------
129 |
130 | // Loader Definition:
131 | // Add new loader to load other picture formats
132 | typedef struct IBITMAP *(*IPICLOADER)(IMDIO *stream, IRGB *pal);
133 |
134 | // setup a new loader:
135 | // using First Byte of the Picture to choose loader for different formats
136 | // NULL for disable the loader
137 | // eg: FirstByte of BMP/GIF/PNG/JPG is 'B'/'G'/0x89/0xff
138 | IPICLOADER ipic_loader(unsigned char firstbyte, IPICLOADER loader);
139 |
140 | // recognize data stream and load picture
141 | struct IBITMAP *iload_picture(IMDIO *stream, IRGB *pal);
142 |
143 |
144 | //---------------------------------------------------------------------
145 | // Picture Saving - Standard Interface
146 | //---------------------------------------------------------------------
147 | // save bmp picture to file
148 | int isave_bmp_file(const char *file, struct IBITMAP *bmp, const IRGB *pal);
149 |
150 | // save tga picture to file
151 | int isave_tga_file(const char *file, struct IBITMAP *bmp, const IRGB *pal);
152 |
153 | // save gif picture to file
154 | int isave_gif_file(const char *file, struct IBITMAP *bmp, const IRGB *pal);
155 |
156 |
157 | //---------------------------------------------------------------------
158 | // ORIGINAL OPERATION
159 | //---------------------------------------------------------------------
160 | struct IBITMAP *ipic_load_file(const char *file, long pos, IRGB *pal);
161 | struct IBITMAP *ipic_load_mem(const void *ptr, long size, IRGB *pal);
162 |
163 | struct IBITMAP *ipic_convert(struct IBITMAP *src, int fmt, const IRGB *pal);
164 |
165 |
166 | //---------------------------------------------------------------------
167 | // GIF INTERFACE (LZW PATENT HAS EXPIRED NOW)
168 | //---------------------------------------------------------------------
169 | struct IGIFDESC /* gif descriptor */
170 | {
171 | int width; /* screen width */
172 | int height; /* screen height */
173 | int bpp; /* color depth */
174 | int state; /* decode state */
175 | int aspect; /* aspect */
176 | int error; /* decode/encode error */
177 | int empty_string; /* lzw - empty_string pointer */
178 | int curr_bit_size; /* lzw - current bit size */
179 | int bit_overflow; /* lzw - is table size greater than 4096 */
180 | int bit_pos; /* lzw - loading bit position */
181 | int data_pos; /* lzw - loading data position */
182 | int data_len; /* lzw - loading data length */
183 | int entire; /* lzw - loading data entire */
184 | int code; /* lzw - code loaded */
185 | int cc; /* lzw - table size */
186 | int string_length; /* lzw - string length */
187 | int bit_size; /* lzw - bit size */
188 | int image_x; /* image descriptor - image x */
189 | int image_y; /* image descriptor - image y */
190 | int image_w; /* image descriptor - image width */
191 | int image_h; /* image descriptor - image height */
192 | int interlace; /* image descriptor - interlace */
193 | int x; /* image descriptor - current x */
194 | int y; /* image descriptor - current y */
195 | int flags; /* flags */
196 | int transparent; /* extension - color transparent */
197 | int method; /* extension - rander method */
198 | long delay; /* extension - time delay */
199 | long frame; /* extension - frame count */
200 | int hotx; /* extension - hotpoint x */
201 | int hoty; /* extension - hotpoint y */
202 | IRGB *pal; /* current palette */
203 | IMDIO *stream; /* input / output stream */
204 | struct IBITMAP *bitmap; /* bitmap */
205 | unsigned char background; /* background color */
206 | unsigned char string[4096]; /* decode string */
207 | unsigned char newc[4096]; /* dict new char */
208 | struct { short base, length; } str[4096]; /* lzw table */
209 | };
210 |
211 | typedef struct IGIFDESC IGIFDESC;
212 |
213 | #define IGIF_ANIMATE 256
214 | #define IGIF_CUSTOMERBMP 512
215 | #define IGIF_EXTMASK 255
216 |
217 |
218 | // load gif header, allocate bitmap if customer is false
219 | int ipic_gif_open(IGIFDESC *gif, IMDIO *stream, IRGB *pal, int customer);
220 |
221 | // close gif and free bitmap
222 | int ipic_gif_close(IGIFDESC *gif);
223 |
224 | // returns delay time, below zero for eof or error
225 | int ipic_gif_read_frame(IGIFDESC *gif);
226 |
227 | // write gif header, allocate bitmap if IGIF_CUSTOMERBMP flag is 0
228 | int ipic_gif_wopen(IGIFDESC *gif, IMDIO *stream, const IRGB *pal,
229 | int w, int h, int background, int aspect, int flags, long hotxy);
230 |
231 | // write frame into gif stream
232 | int ipic_gif_write_frame(IGIFDESC *gif, int delay, int mask, int palsize);
233 |
234 |
235 |
236 | #ifdef __cplusplus
237 | }
238 | #endif
239 |
240 | #endif
241 |
242 |
243 |
--------------------------------------------------------------------------------
/pixellib/mswindx.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/mswindx.c
--------------------------------------------------------------------------------
/pixellib/mswindx.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/mswindx.h
--------------------------------------------------------------------------------
/pixellib/npixel.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/npixel.c
--------------------------------------------------------------------------------
/pixellib/npixel.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/pixellib/npixel.h
--------------------------------------------------------------------------------
/wrap/PixelBitmap.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/wrap/PixelBitmap.cpp
--------------------------------------------------------------------------------
/wrap/PixelBitmap.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/wrap/PixelBitmap.h
--------------------------------------------------------------------------------
/wrap/PixelWin32.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/wrap/PixelWin32.cpp
--------------------------------------------------------------------------------
/wrap/PixelWin32.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skywind3000/pixellib/6769feb9b3b902e206419c05ddbe89d9cc7c19db/wrap/PixelWin32.h
--------------------------------------------------------------------------------