1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // -------------------------------------------------------------------------*/
12 #include "sjme/util.h"
13 #include "lib/scritchui/scritchui.h"
14 #include "lib/scritchui/scritchuiPencil.h"
15 #include "lib/scritchui/scritchuiTypes.h"
16 #include "lib/scritchui/core/coreRaster.h"
17 #include "sjme/debug.h"
18 #include "sjme/fixed.h"
20 sjme_errorCode
sjme_scritchpen_corePrim_rawScanFillInt(
21 sjme_attrInNotNull sjme_scritchui_pencil g
,
22 sjme_attrOutNotNullBuf(rawLen
) void* outRaw
,
23 sjme_attrInPositive sjme_jint outRawOff
,
24 sjme_attrInPositive sjme_jint outRawLen
,
25 sjme_attrInValue sjme_jint rawPixel
,
26 sjme_attrInPositiveNonZero sjme_jint inNumPixels
)
31 if (g
== NULL
|| outRaw
== NULL
)
32 return SJME_ERROR_NULL_ARGUMENTS
;
34 if (outRawOff
< 0 || outRawLen
< 0 || (outRawOff
+ outRawLen
) < 0 ||
36 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
38 /* Determine number of pixels to actually draw. */
39 limit
= inNumPixels
* g
->bytesPerPixel
;
42 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
44 if (outRawLen
< limit
)
48 p
= SJME_POINTER_OFFSET(outRaw
, outRawOff
);
49 for (i
= 0; i
< limit
; i
+= 4)
53 return SJME_ERROR_NONE
;
56 sjme_errorCode
sjme_scritchpen_corePrim_rawScanFillShort(
57 sjme_attrInNotNull sjme_scritchui_pencil g
,
58 sjme_attrOutNotNullBuf(rawLen
) void* outRaw
,
59 sjme_attrInPositive sjme_jint outRawOff
,
60 sjme_attrInPositive sjme_jint outRawLen
,
61 sjme_attrInValue sjme_jint rawPixel
,
62 sjme_attrInPositiveNonZero sjme_jint inNumPixels
)
67 if (g
== NULL
|| outRaw
== NULL
)
68 return SJME_ERROR_NULL_ARGUMENTS
;
70 if (outRawOff
< 0 || outRawLen
< 0 || (outRawOff
+ outRawLen
) < 0 ||
72 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
74 /* Determine number of pixels to actually draw. */
75 limit
= inNumPixels
* g
->bytesPerPixel
;
78 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
80 if (outRawLen
< limit
)
84 p
= SJME_POINTER_OFFSET(outRaw
, outRawOff
);
85 for (i
= 0; i
< limit
; i
+= 2)
89 return SJME_ERROR_NONE
;
92 sjme_errorCode
sjme_scritchpen_corePrim_rawScanFillByte(
93 sjme_attrInNotNull sjme_scritchui_pencil g
,
94 sjme_attrOutNotNullBuf(rawLen
) void* outRaw
,
95 sjme_attrInPositive sjme_jint outRawOff
,
96 sjme_attrInPositive sjme_jint outRawLen
,
97 sjme_attrInValue sjme_jint rawPixel
,
98 sjme_attrInPositiveNonZero sjme_jint inNumPixels
)
103 if (g
== NULL
|| outRaw
== NULL
)
104 return SJME_ERROR_NULL_ARGUMENTS
;
106 if (outRawOff
< 0 || outRawLen
< 0 || (outRawOff
+ outRawLen
) < 0 ||
108 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
110 /* Determine number of pixels to actually draw. */
111 limit
= inNumPixels
* g
->bytesPerPixel
;
114 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
116 if (outRawLen
< limit
)
120 p
= SJME_POINTER_OFFSET(outRaw
, outRawOff
);
121 for (i
= 0; i
< limit
; i
+= 1)
125 return SJME_ERROR_NONE
;
128 sjme_errorCode
sjme_scritchpen_corePrim_rawScanGetNoDest(
129 sjme_attrInNotNull sjme_scritchui_pencil g
,
130 sjme_attrInPositive sjme_jint x
,
131 sjme_attrInPositive sjme_jint y
,
132 sjme_attrOutNotNullBuf(inLen
) void* outData
,
133 sjme_attrInPositiveNonZero sjme_jint inDataLen
,
134 sjme_attrInPositiveNonZero sjme_jint inNumPixels
)
136 if (g
== NULL
|| outData
== NULL
)
137 return SJME_ERROR_NULL_ARGUMENTS
;
139 if (inDataLen
< 0 || inNumPixels
< 0)
140 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
142 /* Just set everything to the first default value. */
143 memset(outData
, 0, inDataLen
);
145 /* Do nothing, there is no reading function. */
146 return SJME_ERROR_NONE
;
149 sjme_errorCode
sjme_scritchpen_coreUtil_blendRGBInto(
150 sjme_attrInNotNull sjme_scritchui_pencil g
,
151 sjme_attrInValue sjme_jboolean destAlpha
,
152 sjme_attrInValue sjme_jboolean srcAlpha
,
153 sjme_attrInValue sjme_jboolean mulAlpha
,
154 sjme_attrInRange(0, 255) sjme_jint mulAlphaValue
,
155 sjme_attrInNotNullBuf(numPixels
) sjme_jint
* dest
,
156 sjme_attrInNotNullBuf(numPixels
) const sjme_jint
* src
,
157 sjme_attrInPositive sjme_jint numPixels
)
160 sjme_fixed sa
, sr
, sg
, sb
, da
, dr
, dg
, db
, iA
, ca
, cr
, cg
, cb
, tff
;
161 sjme_juint srcMask
, destMask
;
163 if (g
== NULL
|| dest
== NULL
|| src
== NULL
)
164 return SJME_ERROR_NULL_ARGUMENTS
;
167 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
169 /* Source and dest mask, if alpha is applicable. */
170 destMask
= (destAlpha
? 0 : UINT32_C(0xFF000000));
171 srcMask
= (srcAlpha
? 0 : UINT32_C(0xFF000000));
173 /* Blend each pixel individually. */
174 /* R(dest) = (R(src) * A(src)) + (R(dest) * (1 - A(src))) */
175 /* G(dest) = (G(src) * A(src)) + (G(dest) * (1 - A(src))) */
176 /* B(dest) = (B(src) * A(src)) + (B(dest) * (1 - A(src))) */
177 /* A(dest) = A(src) + A(dest) - (A(src) * A(dest)) */
178 tff
= sjme_fixed_hi(255);
179 for (i
= 0; i
< numPixels
; i
++)
181 /* Extract as integers first. */
182 da
= ((dest
[i
] | destMask
) >> 24) & 0xFF;
183 dr
= ((dest
[i
]) >> 16) & 0xFF;
184 dg
= ((dest
[i
]) >> 8) & 0xFF;
187 sa
= ((src
[i
] | srcMask
) >> 24) & 0xFF;
188 sr
= ((src
[i
]) >> 16) & 0xFF;
189 sg
= ((src
[i
]) >> 8) & 0xFF;
192 /* Extract components. */
193 da
= sjme_fixed_fraction(da
, 255);
194 dr
= sjme_fixed_fraction(dr
, 255);
195 dg
= sjme_fixed_fraction(dg
, 255);
196 db
= sjme_fixed_fraction(db
, 255);
198 sa
= sjme_fixed_fraction(sa
, 255);
199 sr
= sjme_fixed_fraction(sr
, 255);
200 sg
= sjme_fixed_fraction(sg
, 255);
201 sb
= sjme_fixed_fraction(sb
, 255);
203 iA
= sjme_fixed_hi(1) - sa
;
205 /* A(dest) = A(src) + A(dest) - (A(src) * A(dest)) */
206 ca
= sa
+ da
- sjme_fixed_mul(sa
, da
);
208 /* R(dest) = (R(src) * A(src)) + (R(dest) * (1 - A(src))) */
209 cr
= sjme_fixed_mul(sr
, sa
) + sjme_fixed_mul(dr
, iA
);
211 /* G(dest) = (G(src) * A(src)) + (G(dest) * (1 - A(src))) */
212 cg
= sjme_fixed_mul(sg
, sa
) + sjme_fixed_mul(dg
, iA
);
214 /* B(dest) = (B(src) * A(src)) + (B(dest) * (1 - A(src))) */
215 cb
= sjme_fixed_mul(sb
, sa
) + sjme_fixed_mul(db
, iA
);
217 /* Return the original factor. */
218 ca
= sjme_fixed_ceil(sjme_fixed_mul(ca
, tff
));
219 cr
= sjme_fixed_ceil(sjme_fixed_mul(cr
, tff
));
220 cg
= sjme_fixed_ceil(sjme_fixed_mul(cg
, tff
));
221 cb
= sjme_fixed_ceil(sjme_fixed_mul(cb
, tff
));
224 ca
= sjme_fixed_int(ca
) & 0xFF;
225 cr
= sjme_fixed_int(cr
) & 0xFF;
226 cg
= sjme_fixed_int(cg
) & 0xFF;
227 cb
= sjme_fixed_int(cb
) & 0xFF;
228 dest
[i
] = (ca
<< 24) | (cr
<< 16) | (cg
<< 8) | cb
| destMask
;
232 return SJME_ERROR_NONE
;
235 sjme_errorCode
sjme_scritchpen_coreUtil_rawScanBytes(
236 sjme_attrInNotNull sjme_scritchui_pencil g
,
237 sjme_attrInPositiveNonZero sjme_jint inPixels
,
238 sjme_attrInPositiveNonZero sjme_jint inBytes
,
239 sjme_attrOutNotNull sjme_attrOutPositiveNonZero sjme_jint
* outBytes
,
240 sjme_attrOutNullable sjme_attrOutPositiveNonZero sjme_jint
* outLimit
)
244 if (g
== NULL
|| outBytes
== NULL
)
245 return SJME_ERROR_NULL_ARGUMENTS
;
247 if (inPixels
< 0 || (outLimit
!= NULL
&& inBytes
< 0))
248 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
250 /* Depends on the pixel format. */
252 switch (g
->pixelFormat
)
254 case SJME_GFX_PIXEL_FORMAT_INT_ARGB8888
:
255 case SJME_GFX_PIXEL_FORMAT_INT_RGB888
:
256 case SJME_GFX_PIXEL_FORMAT_INT_BGRA8888
:
257 case SJME_GFX_PIXEL_FORMAT_INT_BGRX8888
:
258 case SJME_GFX_PIXEL_FORMAT_INT_BGR888
:
259 case SJME_GFX_PIXEL_FORMAT_INT_RGBX8888
:
260 result
= inPixels
* 4;
263 case SJME_GFX_PIXEL_FORMAT_BYTE3_RGB888
:
264 case SJME_GFX_PIXEL_FORMAT_BYTE3_BGR888
:
265 result
= inPixels
* 3;
268 case SJME_GFX_PIXEL_FORMAT_SHORT_ARGB4444
:
269 case SJME_GFX_PIXEL_FORMAT_SHORT_RGB565
:
270 case SJME_GFX_PIXEL_FORMAT_SHORT_RGB555
:
271 case SJME_GFX_PIXEL_FORMAT_SHORT_ABGR1555
:
272 case SJME_GFX_PIXEL_FORMAT_SHORT_INDEXED65536
:
273 result
= inPixels
* 2;
276 case SJME_GFX_PIXEL_FORMAT_BYTE_INDEXED256
:
280 case SJME_GFX_PIXEL_FORMAT_PACKED_INDEXED4
:
281 result
= (inPixels
>> 1) + (inPixels
& 1);
284 case SJME_GFX_PIXEL_FORMAT_PACKED_INDEXED2
:
285 result
= (inPixels
>> 2) + ((inPixels
>> 1) & 1);
288 case SJME_GFX_PIXEL_FORMAT_PACKED_INDEXED1
:
289 result
= (inPixels
>> 3) + ((inPixels
>> 2) & 1);
293 /* Make sure what was calculated did not overflow. */
295 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
297 /* Calculate smaller value? */
298 if (outLimit
!= NULL
)
300 /* Use the smaller of the two. */
301 if (result
< inBytes
)
309 return SJME_ERROR_NONE
;
312 sjme_errorCode
sjme_scritchpen_coreUtil_rawScanToRgb(
313 sjme_attrInNotNull sjme_scritchui_pencil g
,
314 sjme_attrInNotNullBuf(outRgbLen
) sjme_jint
* outRgb
,
315 sjme_attrInPositive sjme_jint outRgbOff
,
316 sjme_attrInPositive sjme_jint outRgbLen
,
317 sjme_attrOutNotNullBuf(inRawLen
) const void* inRaw
,
318 sjme_attrInPositive sjme_jint inRawOff
,
319 sjme_attrInPositive sjme_jint inRawLen
)
321 sjme_errorCode error
;
322 sjme_juint destAlphaMask
;
323 sjme_jint limit
, i
, t
, mulShift
, j
;
325 const sjme_jshort
* ss
;
326 const sjme_jbyte
* sb
;
328 sjme_scritchui_pencilColor color
;
330 if (g
== NULL
|| outRgb
== NULL
|| inRaw
== NULL
)
331 return SJME_ERROR_NULL_ARGUMENTS
;
333 if (outRgbOff
< 0 || outRgbLen
< 0 || (outRgbOff
+ outRgbLen
) < 0 ||
334 inRawOff
< 0 || inRawLen
< 0 || (inRawOff
+ inRawLen
) < 0)
335 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
337 /* Destination alpha mask. */
338 destAlphaMask
= (g
->hasAlpha
? 0 : 0xFF000000);
340 /* Determine the type to use for scan reading. */
345 switch (g
->pixelFormat
)
347 case SJME_GFX_PIXEL_FORMAT_INT_ARGB8888
:
348 case SJME_GFX_PIXEL_FORMAT_INT_RGB888
:
349 case SJME_GFX_PIXEL_FORMAT_INT_BGRA8888
:
350 case SJME_GFX_PIXEL_FORMAT_INT_BGRX8888
:
351 case SJME_GFX_PIXEL_FORMAT_INT_BGR888
:
352 case SJME_GFX_PIXEL_FORMAT_INT_RGBX8888
:
353 si
= SJME_POINTER_OFFSET(inRaw
, inRawOff
);
354 limit
= inRawLen
/ 4;
357 case SJME_GFX_PIXEL_FORMAT_BYTE3_RGB888
:
358 case SJME_GFX_PIXEL_FORMAT_BYTE3_BGR888
:
359 sb
= SJME_POINTER_OFFSET(inRaw
, inRawOff
);
360 limit
= inRawLen
/ 3;
364 case SJME_GFX_PIXEL_FORMAT_SHORT_ARGB4444
:
365 case SJME_GFX_PIXEL_FORMAT_SHORT_RGB565
:
366 case SJME_GFX_PIXEL_FORMAT_SHORT_RGB555
:
367 case SJME_GFX_PIXEL_FORMAT_SHORT_ABGR1555
:
368 case SJME_GFX_PIXEL_FORMAT_SHORT_INDEXED65536
:
369 ss
= SJME_POINTER_OFFSET(inRaw
, inRawOff
);
370 limit
= inRawLen
/ 2;
373 case SJME_GFX_PIXEL_FORMAT_BYTE_INDEXED256
:
374 sb
= SJME_POINTER_OFFSET(inRaw
, inRawOff
);
378 case SJME_GFX_PIXEL_FORMAT_PACKED_INDEXED4
:
379 case SJME_GFX_PIXEL_FORMAT_PACKED_INDEXED2
:
380 case SJME_GFX_PIXEL_FORMAT_PACKED_INDEXED1
:
385 return SJME_ERROR_INVALID_ARGUMENT
;
389 d
= &outRgb
[outRgbOff
];
391 /* If the output RGB is smaller than the raw input, limit to it. */
392 if (outRgbLen
< limit
)
395 /* Clear error state. */
396 error
= SJME_ERROR_NONE
;
398 /* Already in the most native format? */
399 if (g
->pixelFormat
== SJME_GFX_PIXEL_FORMAT_INT_ARGB8888
&& si
!= NULL
)
400 memmove(d
, si
, limit
* 4);
403 else if (g
->pixelFormat
== SJME_GFX_PIXEL_FORMAT_INT_RGB888
&& si
!= NULL
)
405 /* Copy and put in the mask. */
406 for (i
= 0; i
< limit
; i
++)
407 *(d
++) = *(si
++) | destAlphaMask
;
410 /* Integer mapping. */
413 for (i
= 0; i
< limit
; i
++)
417 error
|= sjme_scritchpen_corePrim_mapColorFromRaw(g
,
420 *(d
++) = color
.argb
| destAlphaMask
;
427 for (i
= 0; i
< limit
; i
++)
429 t
= *(ss
++) & 0xFFFF;
431 error
|= sjme_scritchpen_corePrim_mapColorFromRaw(g
,
434 *(d
++) = color
.argb
| destAlphaMask
;
439 else if (sb
!= NULL
&& mulShift
== 3)
441 for (i
= 0; i
< limit
; i
++)
443 t
= ((sjme_juint
)(((*(sb
++)) & 0xFF))) << 16;
444 t
|= ((sjme_juint
)(((*(sb
++)) & 0xFF))) << 8;
445 t
|= ((sjme_juint
)(((*(sb
++)) & 0xFF)));
447 error
|= sjme_scritchpen_corePrim_mapColorFromRaw(g
,
450 *(d
++) = color
.argb
| destAlphaMask
;
457 for (i
= 0; i
< limit
; i
++)
461 error
|= sjme_scritchpen_corePrim_mapColorFromRaw(g
,
464 *(d
++) = color
.argb
| destAlphaMask
;
474 /* Failed or success? */
475 if (sjme_error_is(error
))
476 return sjme_error_default(error
);
477 return SJME_ERROR_NONE
;
480 sjme_errorCode
sjme_scritchpen_coreUtil_rgbScanFill(
481 sjme_attrInNotNull sjme_scritchui_pencil g
,
482 sjme_attrOutNotNullBuf(inNumPixels
) sjme_jint
* outRgb
,
483 sjme_attrInPositiveNonZero sjme_jint outRgbOff
,
484 sjme_attrInPositiveNonZero sjme_jint inNumPixels
,
485 sjme_attrInValue sjme_jint inValue
)
490 if (g
== NULL
|| outRgb
== NULL
)
491 return SJME_ERROR_NULL_ARGUMENTS
;
493 if (outRgbOff
< 0 || inNumPixels
< 0 ||
494 (outRgbOff
+ inNumPixels
) < 0)
495 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
497 /* Fill in, which is a rather simple operation. */
498 p
= &outRgb
[outRgbOff
];
499 for (i
= 0; i
< inNumPixels
; i
++)
503 return SJME_ERROR_NONE
;
506 sjme_errorCode
sjme_scritchpen_coreUtil_rgbScanGet(
507 sjme_attrInNotNull sjme_scritchui_pencil g
,
508 sjme_attrInPositive sjme_jint x
,
509 sjme_attrInPositive sjme_jint y
,
510 sjme_attrOutNotNullBuf(inLen
) sjme_jint
* destRgb
,
511 sjme_attrInPositiveNonZero sjme_jint inNumPixels
)
513 sjme_errorCode error
;
514 sjme_jint ex
, rgbBytes
, rawScanBytes
;
517 if (g
== NULL
|| destRgb
== NULL
)
518 return SJME_ERROR_NONE
;
520 /* We cannot access a region outside the image bounds. */
521 ex
= x
+ inNumPixels
;
522 rgbBytes
= inNumPixels
* sizeof(*destRgb
);
523 if (x
< 0 || y
< 0 || inNumPixels
< 0 ||
524 ex
< 0 || ex
> g
->width
|| rgbBytes
< 0)
525 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
527 /* How much data is to be read? */
528 rawScanBytes
= (inNumPixels
* g
->bitsPerPixel
) / 8;
529 if (rawScanBytes
< 0)
530 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
533 rawScan
= sjme_alloca(rawScanBytes
);
535 return SJME_ERROR_OUT_OF_MEMORY
;
538 memset(rawScan
, 0, rawScanBytes
);
540 /* Load in from image directly. */
541 if (sjme_error_is(error
= g
->prim
.rawScanGet(g
,
542 x
, y
, rawScan
, rawScanBytes
, inNumPixels
)))
543 return sjme_error_default(error
);
546 return g
->util
->rawScanToRgb(g
,
547 destRgb
, 0, inNumPixels
,
548 rawScan
, 0, rawScanBytes
);
551 sjme_errorCode
sjme_scritchpen_coreUtil_rgbScanPut(
552 sjme_attrInNotNull sjme_scritchui_pencil g
,
553 sjme_attrInPositive sjme_jint x
,
554 sjme_attrInPositive sjme_jint y
,
555 sjme_attrInNotNullBuf(inLen
) const sjme_jint
* srcRgb
,
556 sjme_attrInPositiveNonZero sjme_jint inNumPixels
,
557 sjme_attrInValue sjme_jboolean srcAlpha
,
558 sjme_attrInValue sjme_jboolean mulAlpha
,
559 sjme_attrInRange(0, 255) sjme_jint mulAlphaValue
)
561 sjme_errorCode error
;
562 sjme_jint ex
, rawScanBytes
, rgbBytes
;
566 if (g
== NULL
|| srcRgb
== NULL
)
567 return SJME_ERROR_NONE
;
569 /* We cannot access a region outside the image bounds. */
570 ex
= x
+ inNumPixels
;
571 rgbBytes
= inNumPixels
* sizeof(*destRgb
);
572 if (x
< 0 || y
< 0 || inNumPixels
< 0 ||
573 ex
< 0 || ex
> g
->width
|| rgbBytes
< 0 ||
574 (mulAlpha
&& (mulAlphaValue
< 0 || mulAlphaValue
> 255)))
575 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
577 /* How much data is to be written? */
578 rawScanBytes
= (inNumPixels
* g
->bitsPerPixel
) / 8;
579 if (rawScanBytes
< 0)
580 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
582 /* Do we need to alpha blend? */
583 if (srcAlpha
|| mulAlpha
)
585 /* Allocate dest RGB data. */
586 destRgb
= sjme_alloca(rgbBytes
);
588 return SJME_ERROR_OUT_OF_MEMORY
;
591 memset(destRgb
, 0, rgbBytes
);
593 /* Load in RGB data from image, which might be lossy. */
594 if (sjme_error_is(error
= g
->util
->rgbScanGet(g
,
595 x
, y
, destRgb
, inNumPixels
)))
596 return sjme_error_default(error
);
598 /* Perform blending. */
599 if (sjme_error_is(error
= g
->util
->blendRGBInto(g
,
600 g
->hasAlpha
, srcAlpha
,
601 mulAlpha
, mulAlphaValue
,
602 destRgb
, srcRgb
, inNumPixels
)))
603 return sjme_error_default(error
);
605 /* The destination becomes the new source. */
609 /* Allocate raw scan data. */
610 rawScan
= sjme_alloca(rawScanBytes
);
612 return SJME_ERROR_OUT_OF_MEMORY
;
615 memset(rawScan
, 0, rawScanBytes
);
617 /* Map from RGB to raw pixels. */
618 if (sjme_error_is(error
= g
->util
->rgbToRawScan(g
,
619 rawScan
, 0, rawScanBytes
,
620 srcRgb
, 0, inNumPixels
)))
621 return sjme_error_default(error
);
623 /* Write direct image data. */
624 return g
->prim
.rawScanPutPure(g
,
626 rawScan
, rawScanBytes
, inNumPixels
);
629 sjme_errorCode
sjme_scritchpen_coreUtil_rgbToRawScan(
630 sjme_attrInNotNull sjme_scritchui_pencil g
,
631 sjme_attrOutNotNullBuf(rawLen
) void* outRaw
,
632 sjme_attrInPositive sjme_jint outRawOff
,
633 sjme_attrInPositive sjme_jint outRawLen
,
634 sjme_attrInNotNullBuf(rgbLen
) const sjme_jint
* inRgb
,
635 sjme_attrInPositive sjme_jint inRgbOff
,
636 sjme_attrInPositive sjme_jint inRgbLen
)
638 sjme_errorCode error
;
639 sjme_jint limit
, i
, t
, mulShift
, j
;
644 sjme_scritchui_pencilColor color
;
646 if (g
== NULL
|| inRgb
== NULL
|| outRaw
== NULL
)
647 return SJME_ERROR_NULL_ARGUMENTS
;
649 if (inRgbOff
< 0 || inRgbLen
< 0 || (inRgbOff
+ inRgbLen
) < 0 ||
650 outRawOff
< 0 || outRawLen
< 0 || (outRawOff
+ outRawLen
) < 0)
651 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
653 /* Determine the type to use for scan reading. */
658 switch (g
->pixelFormat
)
660 case SJME_GFX_PIXEL_FORMAT_INT_ARGB8888
:
661 case SJME_GFX_PIXEL_FORMAT_INT_RGB888
:
662 case SJME_GFX_PIXEL_FORMAT_INT_BGRA8888
:
663 case SJME_GFX_PIXEL_FORMAT_INT_BGRX8888
:
664 case SJME_GFX_PIXEL_FORMAT_INT_BGR888
:
665 case SJME_GFX_PIXEL_FORMAT_INT_RGBX8888
:
666 di
= SJME_POINTER_OFFSET(outRaw
, outRawOff
);
667 limit
= outRawLen
/ 4;
670 case SJME_GFX_PIXEL_FORMAT_BYTE3_RGB888
:
671 case SJME_GFX_PIXEL_FORMAT_BYTE3_BGR888
:
672 db
= SJME_POINTER_OFFSET(outRaw
, outRawOff
);
673 limit
= outRawLen
/ 3;
677 case SJME_GFX_PIXEL_FORMAT_SHORT_ARGB4444
:
678 case SJME_GFX_PIXEL_FORMAT_SHORT_RGB565
:
679 case SJME_GFX_PIXEL_FORMAT_SHORT_RGB555
:
680 case SJME_GFX_PIXEL_FORMAT_SHORT_ABGR1555
:
681 case SJME_GFX_PIXEL_FORMAT_SHORT_INDEXED65536
:
682 ds
= SJME_POINTER_OFFSET(outRaw
, outRawOff
);
683 limit
= outRawLen
/ 2;
686 case SJME_GFX_PIXEL_FORMAT_BYTE_INDEXED256
:
687 db
= SJME_POINTER_OFFSET(outRaw
, outRawOff
);
691 case SJME_GFX_PIXEL_FORMAT_PACKED_INDEXED4
:
692 case SJME_GFX_PIXEL_FORMAT_PACKED_INDEXED2
:
693 case SJME_GFX_PIXEL_FORMAT_PACKED_INDEXED1
:
698 return SJME_ERROR_INVALID_ARGUMENT
;
702 s
= &inRgb
[inRgbOff
];
704 /* If the output RGB is smaller than the raw input, limit to it. */
705 if (inRgbLen
< limit
)
708 /* Clear error state. */
709 error
= SJME_ERROR_NONE
;
711 /* Already in the most native format? */
712 if (g
->pixelFormat
== SJME_GFX_PIXEL_FORMAT_INT_ARGB8888
&& di
!= NULL
)
713 memmove(di
, s
, limit
* 4);
716 else if (g
->pixelFormat
== SJME_GFX_PIXEL_FORMAT_INT_RGB888
&& di
!= NULL
)
718 /* Copy and put in the mask. */
719 for (i
= 0; i
< limit
; i
++)
723 /* Integer mapping. */
726 for (i
= 0; i
< limit
; i
++)
730 error
|= sjme_scritchpen_corePrim_mapColorFromRGB(g
,
740 for (i
= 0; i
< limit
; i
++)
744 error
|= sjme_scritchpen_corePrim_mapColorFromRGB(g
,
747 *(ds
++) = color
.v
& 0xFFFF;
752 else if (db
!= NULL
&& mulShift
== 3)
754 for (i
= 0; i
< limit
; i
++)
758 error
|= sjme_scritchpen_corePrim_mapColorFromRGB(g
,
761 *(db
++) = (color
.v
>> 16) & 0xFF;
762 *(db
++) = (color
.v
>> 8) & 0xFF;
763 *(db
++) = (color
.v
) & 0xFF;
770 for (i
= 0; i
< limit
; i
++)
774 error
|= sjme_scritchpen_corePrim_mapColorFromRGB(g
,
777 *(db
++) = color
.v
& 0xFF;
787 /* Failed or success? */
788 if (sjme_error_is(error
))
789 return sjme_error_default(error
);
790 return SJME_ERROR_NONE
;