1 /*
2 * ppui/Graphics_16BIT.cpp
3 *
4 * Copyright 2009 Peter Barth
5 *
6 * This file is part of Milkytracker.
7 *
8 * Milkytracker is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * Milkytracker is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with Milkytracker. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23 #include "Graphics.h"
24 #include "Font.h"
25 #include "fastfill.h"
26
27 #define BPP 2
28
PPGraphics_16BIT(pp_int32 w,pp_int32 h,pp_int32 p,void * buff)29 PPGraphics_16BIT::PPGraphics_16BIT(pp_int32 w, pp_int32 h, pp_int32 p, void* buff) :
30 PPGraphicsFrameBuffer(w, h, p, buff)
31 {
32 }
33
setPixel(pp_int32 x,pp_int32 y)34 void PPGraphics_16BIT::setPixel(pp_int32 x, pp_int32 y)
35 {
36 if (y >= currentClipRect.y1 && y < currentClipRect.y2 &&
37 x >= currentClipRect.x1 && x < currentClipRect.x2)
38 {
39 pp_uint16* buff = (pp_uint16*)buffer+(pitch>>1)*y+x;
40
41 *buff = color16;
42 }
43 }
44
setPixel(pp_int32 x,pp_int32 y,const PPColor & color)45 void PPGraphics_16BIT::setPixel(pp_int32 x, pp_int32 y, const PPColor& color)
46 {
47 if (y >= currentClipRect.y1 && y < currentClipRect.y2 &&
48 x >= currentClipRect.x1 && x < currentClipRect.x2)
49 {
50 pp_uint16 col16 = (((pp_uint16)((color.r)>>3)<<11)+((pp_uint16)((color.g)>>2)<<5)+(pp_uint16)((color.b)>>3));
51 pp_uint16* buff = (pp_uint16*)buffer+(pitch>>1)*y+x;
52 *buff = col16;
53 }
54 }
55
fill(PPRect rect)56 void PPGraphics_16BIT::fill(PPRect rect)
57 {
58
59 if (rect.y1 < currentClipRect.y1)
60 rect.y1 = currentClipRect.y1;
61
62 if (rect.x1 < currentClipRect.x1)
63 rect.x1 = currentClipRect.x1;
64
65 if (rect.y2 > currentClipRect.y2)
66 rect.y2 = currentClipRect.y2;
67
68 if (rect.x2 > currentClipRect.x2)
69 rect.x2 = currentClipRect.x2;
70
71 pp_uint32 col32 = (((pp_uint32)color16) << 16) + color16;
72
73 const pp_int32 hPitch = pitch>>1;
74
75 pp_uint16* dest = (pp_uint16*)buffer+hPitch*rect.y1+rect.x1;
76
77 const pp_int32 width = rect.x2 - rect.x1;
78 const pp_int32 height = rect.y2 - rect.y1;
79
80 const pp_int16 color16 = this->color16;
81
82 for (pp_int32 y = 0; y < height; y++)
83 {
84 pp_uint16* buff = dest;
85
86 pp_int32 len = width;
87
88 if (reinterpret_cast<size_t> (buff) & 3)
89 {
90 *buff++ = color16;
91 len--;
92 }
93
94 pp_uint32* buff32 = (pp_uint32*)buff;
95
96 fill_dword(buff32, col32, len>>1);
97
98 if (len&1)
99 *((pp_uint16*)(buff32+(len>>1))) = color16;
100
101 dest+=hPitch;
102 }
103
104 }
105
fill()106 void PPGraphics_16BIT::fill()
107 {
108
109 fill(currentClipRect);
110
111 }
112
drawHLine(pp_int32 x1,pp_int32 x2,pp_int32 y)113 void PPGraphics_16BIT::drawHLine(pp_int32 x1, pp_int32 x2, pp_int32 y)
114 {
115
116 pp_int32 lx = x1;
117 pp_int32 rx = x2;
118
119 if (x1 > x2)
120 {
121 pp_int32 h = x2;
122 x2 = x1;
123 x1 = h;
124 }
125
126 if (lx < currentClipRect.x1)
127 lx = currentClipRect.x1;
128
129 if (rx > currentClipRect.x2)
130 rx = currentClipRect.x2;
131
132 if (y < currentClipRect.y1)
133 return;
134
135 if (y >= currentClipRect.y2)
136 return;
137
138 pp_uint32 col32 = (((pp_uint32)color16) << 16) + color16;
139
140 pp_uint16* buff = (pp_uint16*)buffer+(pitch>>1)*y+lx;
141
142 pp_int32 len = rx-lx;
143
144 if (len <= 0)
145 return;
146
147 if (reinterpret_cast<size_t> (buff) & 3)
148 {
149 *buff++ = color16;
150 len--;
151 }
152
153 pp_uint32* buff32 = (pp_uint32*)buff;
154
155 fill_dword(buff32, col32, len>>1);
156
157 if (len&1)
158 *((pp_uint16*)(buff32+(len>>1))) = color16;
159 }
160
drawVLine(pp_int32 y1,pp_int32 y2,pp_int32 x)161 void PPGraphics_16BIT::drawVLine(pp_int32 y1, pp_int32 y2, pp_int32 x)
162 {
163
164 pp_int32 ly = y1;
165 pp_int32 ry = y2;
166
167 if (y1 > y2)
168 {
169 pp_int32 h = y2;
170 y2 = y1;
171 y1 = h;
172 }
173
174 if (ly < currentClipRect.y1)
175 ly = currentClipRect.y1;
176
177 if (ry > currentClipRect.y2)
178 ry = currentClipRect.y2;
179
180 if (x < currentClipRect.x1)
181 return;
182
183 if (x >= currentClipRect.x2)
184 return;
185
186 pp_uint16* buff = (pp_uint16*)buffer+(pitch>>1)*ly+x;
187
188 for (pp_int32 y = ly; y < ry; y++)
189 {
190 *buff = color16;
191 buff+=pitch>>1;
192 }
193
194 }
195
drawLine(pp_int32 x1,pp_int32 y1,pp_int32 x2,pp_int32 y2)196 void PPGraphics_16BIT::drawLine(pp_int32 x1, pp_int32 y1, pp_int32 x2, pp_int32 y2)
197 {
198 __PPGRAPHICSLINETEMPLATE
199 }
200
drawAntialiasedLine(pp_int32 x1,pp_int32 y1,pp_int32 x2,pp_int32 y2)201 void PPGraphics_16BIT::drawAntialiasedLine(pp_int32 x1, pp_int32 y1, pp_int32 x2, pp_int32 y2)
202 {
203 __PPGRAPHICSAALINETEMPLATE
204 }
205
blit(const pp_uint8 * src,const PPPoint & p,const PPSize & size,pp_uint32 pitch,pp_uint32 bpp,pp_int32 intensity)206 void PPGraphics_16BIT::blit(const pp_uint8* src, const PPPoint& p, const PPSize& size, pp_uint32 pitch, pp_uint32 bpp, pp_int32 intensity/* = 256*/)
207 {
208 pp_int32 w = size.width;
209 pp_int32 h = size.height;
210
211 const pp_uint32 bytesPerPixel = bpp;
212
213 if (intensity == 256)
214 {
215 pp_uint16* dst = (pp_uint16*)((pp_uint8*)buffer+(this->pitch*p.y+p.x*BPP));
216 for (pp_int32 y = 0; y < h; y++)
217 {
218 for (pp_int32 x = 0; x < w; x++)
219 {
220 *dst = (((pp_uint16)((src[0])>>3)<<11)+((pp_uint16)((src[1])>>2)<<5)+(pp_uint16)((src[2])>>3));
221 dst++;
222 src+=bytesPerPixel;
223 }
224 dst+=this->pitch/BPP - w;
225 src+=pitch - w*bytesPerPixel;
226 }
227 }
228 else
229 {
230 pp_uint16* dst = (pp_uint16*)((pp_uint8*)buffer+(this->pitch*p.y+p.x*BPP));
231 for (pp_int32 y = 0; y < h; y++)
232 {
233 for (pp_int32 x = 0; x < w; x++)
234 {
235 *dst = (((pp_uint16)((src[0]*intensity/256)>>3)<<11)+((pp_uint16)((src[1]*intensity/256)>>2)<<5)+(pp_uint16)((src[2]*intensity/256)>>3));
236 dst++;
237 src+=bytesPerPixel;
238 }
239 dst+=this->pitch/BPP - w;
240 src+=pitch - w*bytesPerPixel;
241 }
242 }
243 }
244
drawChar(pp_uint8 chr,pp_int32 x,pp_int32 y,bool underlined)245 void PPGraphics_16BIT::drawChar(pp_uint8 chr, pp_int32 x, pp_int32 y, bool underlined)
246 {
247
248 if (currentFont == NULL)
249 return;
250
251
252 pp_int32 charWidth = (signed)currentFont->getCharWidth();
253 pp_int32 charHeight = (signed)currentFont->getCharHeight();
254 pp_int32 charDim = currentFont->charDim;
255
256 if (x + (signed)charWidth < currentClipRect.x1 ||
257 x > currentClipRect.x2 ||
258 y + (signed)charHeight < currentClipRect.y1 ||
259 y > currentClipRect.y2)
260 return;
261
262 /*pp_uint8 r = (pp_uint8)currentColor.r;
263 pp_uint8 g = (pp_uint8)currentColor.g;
264 pp_uint8 b = (pp_uint8)currentColor.b;
265
266 if (x>= currentClipRect.x1 && x + (signed)currentFont->charWidth < currentClipRect.x2 &&
267 y>= currentClipRect.y1 && y + (signed)currentFont->charHeight < currentClipRect.y2)
268 {
269 for (pp_uint32 i = 0; i < currentFont->charHeight; i++)
270 {
271 pp_uint8* buff = (pp_uint8*)buffer + (y+i)*pitch + x*3;
272 for (pp_uint32 j = 0; j < currentFont->charWidth; j++)
273 {
274
275 if (currentFont->getPixelBit(chr, j,i))
276 {
277 buff[0] = b;
278 buff[1] = g;
279 buff[2] = r;
280 }
281 buff+=3;
282 }
283 }
284 }
285 else
286 {
287 for (pp_uint32 i = 0; i < currentFont->charHeight; i++)
288 for (pp_uint32 j = 0; j < currentFont->charWidth; j++)
289 {
290
291 if (y+(signed)i >= currentClipRect.y1 && y+(signed)i < currentClipRect.y2 &&
292 x+(signed)j >= currentClipRect.x1 && x+(signed)j < currentClipRect.x2 &&
293 currentFont->getPixelBit(chr, j,i))
294 {
295
296 pp_uint8* buff = (pp_uint8*)buffer+((y+i)*pitch+(x+j)*3);
297
298 buff[0] = b;
299 buff[1] = g;
300 buff[2] = r;
301
302 }
303 }
304
305 }*/
306 Bitstream* bitstream = currentFont->bitstream;
307 pp_uint8* fontbuffer = bitstream->buffer;
308
309 pp_uint16* buff = (pp_uint16*)buffer+(pitch>>1)*y+x;
310
311 const pp_uint32 cchrDim = chr*charDim;
312 const pp_uint32 incr = (pitch>>1)-(charWidth);
313
314 if (x>= currentClipRect.x1 && x + charWidth < currentClipRect.x2 &&
315 y>= currentClipRect.y1 && y + charHeight < currentClipRect.y2)
316 {
317
318 pp_uint32 yChr = cchrDim;
319 for (pp_uint32 i = 0; i < (unsigned)charHeight; i++)
320 {
321 pp_uint32 xChr = yChr;
322 for (pp_uint32 j = 0; j < (unsigned)charWidth; j++)
323 {
324 if ((fontbuffer[xChr>>3]>>(xChr&7)&1))
325 {
326 *buff = color16;
327 }
328 buff++;
329 xChr++;
330 }
331
332 buff+=incr;
333 yChr+=charWidth;
334 }
335 }
336 else
337 {
338 pp_uint32 yChr = cchrDim;
339 for (pp_uint32 i = 0; i < (unsigned)charHeight; i++)
340 {
341 pp_uint32 xChr = yChr;
342 for (pp_uint32 j = 0; j < (unsigned)charWidth; j++)
343 {
344
345 if (y+(signed)i >= currentClipRect.y1 && y+(signed)i < currentClipRect.y2 &&
346 x+(signed)j >= currentClipRect.x1 && x+(signed)j < currentClipRect.x2 &&
347 (fontbuffer[xChr>>3]>>(xChr&7)&1))
348 {
349
350 pp_uint16* buff = (pp_uint16*)buffer+(pitch>>1)*(y+i)+(x+j);
351 *buff = color16;
352 }
353 xChr++;
354
355 }
356 yChr+=charWidth;
357 }
358
359 }
360
361 if (underlined)
362 drawHLine(x, x+charWidth, y+charHeight);
363
364 }
365
drawString(const char * str,pp_int32 x,pp_int32 y,bool underlined)366 void PPGraphics_16BIT::drawString(const char* str, pp_int32 x, pp_int32 y, bool underlined/* = false*/)
367 {
368 if (currentFont == NULL)
369 return;
370
371 pp_int32 charWidth = (signed)currentFont->getCharWidth();
372 pp_int32 charHeight = (signed)currentFont->getCharHeight();
373
374 pp_int32 sx = x;
375
376 while (*str)
377 {
378 switch (*str)
379 {
380 case '\xf4':
381 setPixel(x+(charWidth>>1), y+(charHeight>>1));
382 break;
383 case '\n':
384 y+=charHeight;
385 x=sx-charWidth;
386 break;
387 default:
388 drawChar(*str, x, y, underlined);
389 }
390 x += charWidth;
391 str++;
392 }
393 }
394
drawStringVertical(const char * str,pp_int32 x,pp_int32 y,bool underlined)395 void PPGraphics_16BIT::drawStringVertical(const char* str, pp_int32 x, pp_int32 y, bool underlined/* = false*/)
396 {
397 if (currentFont == NULL)
398 return;
399
400 pp_int32 charWidth = (signed)currentFont->getCharWidth();
401 pp_int32 charHeight = (signed)currentFont->getCharHeight();
402
403 while (*str)
404 {
405 switch (*str)
406 {
407 case '\xf4':
408 setPixel(x+(charWidth>>1), y+(charHeight>>1));
409 break;
410 default:
411 drawChar(*str, x, y, underlined);
412 }
413 y += charHeight;
414 str++;
415 }
416 }
417