When copying parameters, untranslate first before because otherwise copying will...
[SquirrelJME.git] / nanocoat / lib / scritchui / scritchPencilRasterMisc.c
blob47e9cab44a0e90dff3732a04cfd241031321d432
1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // SquirrelJME
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 // -------------------------------------------------------------------------*/
10 #include <string.h>
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_mapColorFromRGB(
21 sjme_attrInNotNull sjme_scritchui_pencil g,
22 sjme_attrInValue sjme_jint argb,
23 sjme_attrOutNotNull sjme_scritchui_pencilColor* outColor)
25 sjme_jint v, aa, rr, gg, bb, ii;
26 sjme_jint i, numCol, d, bestCol, bestColScore, thisColScore;
27 sjme_jint pargb, prr, pgg, pbb;
28 sjme_jint mrr, mgg, mbb;
29 const sjme_jint* colors;
31 if (g == NULL || outColor == NULL)
32 return SJME_ERROR_NULL_ARGUMENTS;
34 /* Set base color properties. */
35 aa = (argb >> 24) & 0xFF;
36 outColor->a = aa;
37 rr = (argb >> 16) & 0xFF;
38 outColor->r = rr;
39 gg = (argb >> 8) & 0xFF;
40 outColor->g = gg;
41 bb = (argb) & 0xFF;
42 outColor->b = bb;
44 /* Find closest indexed color. */
45 ii = -1;
46 numCol = g->palette.numColors;
47 if (g->palette.colors != NULL && numCol > 0)
49 /* Clear alpha. */
50 d = argb & 0xFFFFFF;
52 /* Determine the most important color channel. */
53 mrr = (rr >= gg && rr >= bb ? 1 : 2);
54 mgg = (gg >= rr && gg >= bb ? 1 : 2);
55 mbb = (bb >= rr && bb >= gg ? 1 : 2);
57 /* Start with a horrible color score. */
58 bestCol = 0;
59 bestColScore = 134217728;
61 /* Find exact color match? */
62 colors = g->palette.colors;
63 for (i = 0; i < numCol; i++)
65 /* Exact match? */
66 pargb = colors[i] & 0xFFFFFF;
67 if (d == pargb)
69 ii = i;
70 break;
73 /* Get original RGB value. */
74 prr = (pargb >> 16) & 0xFF;
75 pgg = (pargb >> 8) & 0xFF;
76 pbb = (pargb) & 0xFF;
78 /* Calculate this color score, use if it is better. */
79 thisColScore = (abs(prr - rr) * mrr) +
80 (abs(pgg - gg) * mgg) +
81 (abs(pbb - bb) * mbb);
82 if (thisColScore < bestColScore)
84 bestCol = i;
85 bestColScore = thisColScore;
89 /* If no exact color was found, use the best scoring one. */
90 if (ii < 0)
91 ii = bestCol;
94 /* Determine raw pixel color. */
95 switch (g->pixelFormat)
97 case SJME_GFX_PIXEL_FORMAT_INT_ARGB8888:
98 v = argb;
99 break;
101 case SJME_GFX_PIXEL_FORMAT_INT_BGRA8888:
102 v = (bb << 24) | (gg << 16) | (rr << 8) | aa;
103 break;
105 case SJME_GFX_PIXEL_FORMAT_INT_BGRX8888:
106 v = (bb << 24) | (gg << 16) | (rr << 8) | 0xFF;
107 break;
109 case SJME_GFX_PIXEL_FORMAT_INT_BGR888:
110 v = 0xFF000000 | (bb << 16) | (gg << 8) | (rr);
111 break;
113 case SJME_GFX_PIXEL_FORMAT_INT_RGBX8888:
114 v = (rr << 24) | (gg << 16) | (bb << 8) | 0xFF;
115 break;
117 case SJME_GFX_PIXEL_FORMAT_INT_RGB888:
118 v = argb | 0xFF000000;
119 break;
121 case SJME_GFX_PIXEL_FORMAT_BYTE3_RGB888:
122 v = (rr << 16) | (gg << 8) | bb;
123 break;
125 case SJME_GFX_PIXEL_FORMAT_BYTE3_BGR888:
126 v = (rr) | (gg << 8) | (bb << 16);
127 break;
129 case SJME_GFX_PIXEL_FORMAT_SHORT_ARGB4444:
130 v = (((aa >> 4) & 0xF) << 12) |
131 (((rr >> 4) & 0xF) << 8) |
132 (((gg >> 4) & 0xF) << 4) |
133 ((bb >> 4) & 0xF);
134 break;
136 case SJME_GFX_PIXEL_FORMAT_SHORT_RGB565:
137 v = (((rr >> 3) & 0x1F) << 11) |
138 (((gg >> 2) & 0x3F) << 5) |
139 ((bb >> 3) & 0x1F);
140 break;
142 case SJME_GFX_PIXEL_FORMAT_SHORT_RGB555:
143 v = (((rr >> 3) & 0x1F) << 10) |
144 (((gg >> 3) & 0x1F) << 5) |
145 ((bb >> 3) & 0x1F);
146 break;
148 case SJME_GFX_PIXEL_FORMAT_SHORT_ABGR1555:
149 v = (((aa >> 7) & 0x1) << 15) |
150 (((bb >> 3) & 0x1F) << 10) |
151 (((gg >> 3) & 0x1F) << 5) |
152 ((rr >> 3) & 0x1F);
153 break;
155 case SJME_GFX_PIXEL_FORMAT_SHORT_INDEXED65536:
156 v = ii & 0xFFFF;
157 break;
159 case SJME_GFX_PIXEL_FORMAT_BYTE_INDEXED256:
160 v = ii & 0xFF;
161 break;
163 case SJME_GFX_PIXEL_FORMAT_PACKED_INDEXED4:
164 v = ii & 0xF;
165 break;
167 case SJME_GFX_PIXEL_FORMAT_PACKED_INDEXED2:
168 v = ii & 0x3;
169 break;
171 case SJME_GFX_PIXEL_FORMAT_PACKED_INDEXED1:
172 v = ii & 0x1;
173 break;
176 /* Store raw colors. */
177 outColor->i = ii;
178 outColor->v = v;
179 outColor->argb = argb;
181 /* Success! */
182 return SJME_ERROR_NONE;
185 sjme_errorCode sjme_scritchpen_corePrim_mapColorFromRaw(
186 sjme_attrInNotNull sjme_scritchui_pencil g,
187 sjme_attrInValue sjme_jint v,
188 sjme_attrOutNotNull sjme_scritchui_pencilColor* outColor)
190 sjme_jint numCol, aa, rr, gg, bb, argb;
192 if (g == NULL || outColor == NULL)
193 return SJME_ERROR_NULL_ARGUMENTS;
195 /* If there is a palette, try using it to get a color. */
196 numCol = g->palette.numColors;
197 if (g->palette.colors != NULL && numCol > 0)
199 if (v > 0 && v < numCol)
200 return sjme_scritchpen_corePrim_mapColorFromRGB(g,
201 g->palette.colors[v], outColor);
203 /* Invalid color, render to black or close to it. */
204 return sjme_scritchpen_corePrim_mapColorFromRGB(g,
205 0, outColor);
208 /* Initial map to black. */
209 aa = 0;
210 rr = 0;
211 gg = 0;
212 bb = 0;
214 /* Recover raw pixel color. */
215 switch (g->pixelFormat)
217 case SJME_GFX_PIXEL_FORMAT_INT_ARGB8888:
218 aa = (v >> 24) & 0xFF;
219 rr = (v >> 16) & 0xFF;
220 gg = (v >> 8) & 0xFF;
221 bb = (v) & 0xFF;
222 break;
224 case SJME_GFX_PIXEL_FORMAT_INT_BGRA8888:
225 aa = (v) & 0xFF;
226 rr = (v >> 8) & 0xFF;
227 gg = (v >> 16) & 0xFF;
228 bb = (v >> 24) & 0xFF;
229 break;
231 case SJME_GFX_PIXEL_FORMAT_INT_BGRX8888:
232 aa = 0xFF;
233 rr = (v >> 8) & 0xFF;
234 gg = (v >> 16) & 0xFF;
235 bb = (v >> 24) & 0xFF;
236 break;
238 case SJME_GFX_PIXEL_FORMAT_INT_BGR888:
239 case SJME_GFX_PIXEL_FORMAT_BYTE3_BGR888:
240 aa = 0xFF;
241 rr = (v) & 0xFF;
242 gg = (v >> 8) & 0xFF;
243 bb = (v >> 16) & 0xFF;
244 break;
246 case SJME_GFX_PIXEL_FORMAT_INT_RGB888:
247 case SJME_GFX_PIXEL_FORMAT_BYTE3_RGB888:
248 aa = 0xFF;
249 rr = (v >> 16) & 0xFF;
250 gg = (v >> 8) & 0xFF;
251 bb = (v) & 0xFF;
252 break;
254 case SJME_GFX_PIXEL_FORMAT_INT_RGBX8888:
255 aa = 0xFF;
256 rr = (v >> 24) & 0xFF;
257 gg = (v >> 16) & 0xFF;
258 bb = (v >> 8) & 0xFF;
259 break;
261 case SJME_GFX_PIXEL_FORMAT_SHORT_ARGB4444:
262 aa = ((v >> 12) & 0xF);
263 aa |= aa << 4;
264 rr = ((v >> 8) & 0xF);
265 rr |= rr << 4;
266 gg = ((v >> 4) & 0xF);
267 gg |= gg << 4;
268 bb = ((v) & 0xF);
269 bb |= bb << 4;
270 break;
272 case SJME_GFX_PIXEL_FORMAT_SHORT_RGB565:
273 aa = 0xFF;
274 rr = ((v >> 11) & 0x1F) << 3;
275 gg = ((v >> 4) & 0x3F) << 2;
276 bb = ((v) & 0x1F) << 3;
277 break;
279 case SJME_GFX_PIXEL_FORMAT_SHORT_RGB555:
280 aa = 0xFF;
281 rr = ((v >> 10) & 0x1F) << 3;
282 gg = ((v >> 5) & 0x1F) << 3;
283 bb = ((v) & 0x1F) << 3;
284 break;
286 case SJME_GFX_PIXEL_FORMAT_SHORT_ABGR1555:
287 sjme_todo("Impl?");
288 v = (((aa >> 7) & 0x1) << 15) |
289 (((bb >> 3) & 0x1F) << 10) |
290 (((gg >> 3) & 0x1F) << 5) |
291 ((rr >> 3) & 0x1F);
292 break;
295 /* Map back to normalize. */
296 argb = (aa << 24) | (rr << 16) | (gg << 8) | bb;
297 outColor->argb = argb;
298 return sjme_scritchpen_corePrim_mapColorFromRGB(g, argb, outColor);
301 sjme_errorCode sjme_scritchpen_corePrim_mapColor(
302 sjme_attrInNotNull sjme_scritchui_pencil g,
303 sjme_attrInValue sjme_jboolean fromRaw,
304 sjme_attrInValue sjme_jint inRgbOrRaw,
305 sjme_attrOutNotNull sjme_scritchui_pencilColor* outColor)
307 if (g == NULL || outColor == NULL)
308 return SJME_ERROR_NULL_ARGUMENTS;
310 /* Otherwise, use our own colormapping code. */
311 if (fromRaw)
312 return sjme_scritchpen_corePrim_mapColorFromRaw(g,
313 inRgbOrRaw, outColor);
314 return sjme_scritchpen_corePrim_mapColorFromRGB(g,
315 inRgbOrRaw, outColor);
318 sjme_errorCode sjme_scritchpen_coreUtil_applyAnchor(
319 sjme_attrInValue sjme_jint anchor,
320 sjme_attrInValue sjme_jint x,
321 sjme_attrInValue sjme_jint y,
322 sjme_attrInPositive sjme_jint w,
323 sjme_attrInPositive sjme_jint h,
324 sjme_attrInValue sjme_jint baseline,
325 sjme_attrOutNotNull sjme_jint* outX,
326 sjme_attrOutNotNull sjme_jint* outY)
328 if (outX == NULL || outY == NULL)
329 return SJME_ERROR_NULL_ARGUMENTS;
331 /* Cannot be negative. */
332 if (w < 0 || h < 0)
333 return SJME_ERROR_INVALID_ARGUMENT;
335 /* Horizontal anchoring. */
336 if ((anchor & SJME_SCRITCHUI_ANCHOR_LEFT) == 0)
338 if ((anchor & SJME_SCRITCHUI_ANCHOR_HCENTER) != 0)
339 x -= w / 2;
340 else if ((anchor & SJME_SCRITCHUI_ANCHOR_RIGHT) != 0)
341 x -= w;
344 /* Vertical anchoring. */
345 if ((anchor & SJME_SCRITCHUI_ANCHOR_TOP) == 0)
347 if ((anchor & SJME_SCRITCHUI_ANCHOR_VCENTER) != 0)
348 y -= h / 2;
349 else if ((anchor & SJME_SCRITCHUI_ANCHOR_BOTTOM) != 0)
350 y -= h;
351 else if ((anchor & SJME_SCRITCHUI_ANCHOR_BASELINE) != 0)
352 y -= baseline;
355 /* Success! */
356 *outX = x;
357 *outY = y;
358 return SJME_ERROR_NONE;
361 sjme_errorCode sjme_scritchpen_coreUtil_applyRotateScale(
362 sjme_attrOutNotNull sjme_scritchui_pencilMatrix* outMatrix,
363 sjme_attrInValue sjme_scritchui_pencilTranslate inTrans,
364 sjme_attrInPositive sjme_jint wSrc,
365 sjme_attrInPositive sjme_jint hSrc,
366 sjme_attrInPositive sjme_jint wDest,
367 sjme_attrInPositive sjme_jint hDest)
369 sjme_scritchui_pencilMatrix result;
370 sjme_fixed scaleX, scaleY, temp;
371 sjme_jint xform;
373 if (outMatrix == NULL)
374 return SJME_ERROR_NULL_ARGUMENTS;
376 /* Initialize. */
377 memset(&result, 0, sizeof(result));
379 /* Perform total image scaling first. */
380 scaleX = sjme_fixed_fraction(wSrc, wDest);
381 scaleY = sjme_fixed_fraction(hSrc, hDest);
383 /* This is simple enough to calculate, is just the destination. */
384 result.tw = wDest;
385 result.th = hDest;
387 /* Determine the transformation functions to use. There are just three */
388 /* primitive transformation functions: flip horizontally, then */
389 /* flip vertically, then rotate 90 degrees clockwise. This handles */
390 /* every transformation which fill every single bit. */
391 switch (inTrans)
393 /* These bits represent the stuff to do! == 0b9VH; */
394 case SJME_SCRITCHUI_TRANS_NONE: xform = 0b000; break;
395 case SJME_SCRITCHUI_TRANS_MIRROR: xform = 0b001; break;
396 case SJME_SCRITCHUI_TRANS_MIRROR_ROT180: xform = 0b010; break;
397 case SJME_SCRITCHUI_TRANS_ROT180: xform = 0b011; break;
398 case SJME_SCRITCHUI_TRANS_ROT90: xform = 0b100; break;
399 case SJME_SCRITCHUI_TRANS_MIRROR_ROT90: xform = 0b101; break;
400 case SJME_SCRITCHUI_TRANS_MIRROR_ROT270: xform = 0b110; break;
401 case SJME_SCRITCHUI_TRANS_ROT270: xform = 0b111; break;
402 /* These bits represent the stuff to do! == 0b9VH; */
405 /* Start with this. */
406 result.x.wx = scaleX;
407 result.y.zy = scaleY;
409 /* Mirror horizontally? */
410 if ((xform & 0b001) != 0)
411 result.x.wx = -result.x.wx;
413 /* Mirror vertically? */
414 if ((xform & 0b010) != 0)
415 result.y.zy = -result.y.zy;
417 /* Rotate 90 degrees clockwise */
418 /* Thanks to jercos for helping out with the matrix math! */
419 /* The math here has been simplified to remove constants and otherwise. */
420 if ((xform & 0b100) != 0)
422 temp = result.x.wx;
423 result.x.wx = result.x.zy;
424 result.x.zy = -temp;
426 temp = result.y.wx;
427 result.y.wx = result.y.zy;
428 result.y.zy = -temp;
431 /* Success! */
432 memmove(outMatrix, &result, sizeof(result));
433 return SJME_ERROR_NONE;
436 sjme_errorCode sjme_scritchpen_coreUtil_applyTranslate(
437 sjme_attrInNotNull sjme_scritchui_pencil g,
438 sjme_attrInOutNotNull sjme_jint* x,
439 sjme_attrInOutNotNull sjme_jint* y)
441 if (g == NULL || x == NULL || y == NULL)
442 return SJME_ERROR_NULL_ARGUMENTS;
444 /* Apply translation. */
445 (*x) += g->state.translate.x;
446 (*y) += g->state.translate.y;
448 /* Success! */
449 return SJME_ERROR_NONE;
452 sjme_errorCode sjme_scritchpen_core_mapColor(
453 sjme_attrInNotNull sjme_scritchui_pencil g,
454 sjme_attrInValue sjme_jboolean fromRaw,
455 sjme_attrInValue sjme_jint inRgbOrRaw,
456 sjme_attrOutNotNull sjme_scritchui_pencilColor* outColor)
458 if (g == NULL || outColor == NULL)
459 return SJME_ERROR_NULL_ARGUMENTS;
461 /* Use primitive function. */
462 return g->prim.mapColor(g, fromRaw, inRgbOrRaw, outColor);
465 sjme_errorCode sjme_scritchpen_core_setAlphaColor(
466 sjme_attrInNotNull sjme_scritchui_pencil g,
467 sjme_attrInValue sjme_jint argb)
469 sjme_errorCode error;
470 sjme_scritchui_pencilColor* target;
472 if (g == NULL)
473 return SJME_ERROR_NULL_ARGUMENTS;
475 /* Map color natively, if possible. */
476 target = &g->state.color;
477 if (sjme_error_is(error = g->prim.mapColor(g,
478 SJME_JNI_FALSE, argb, target)))
479 return sjme_error_default(error);
481 /* Is alpha applicable? */
482 /* Note that if we cannot read from the source buffer, we cannot */
483 /* apply alpha correctly so we just ignore it. */
484 g->state.applyAlpha = (target->a != 0xFF &&
485 g->prim.rawScanGet != NULL &&
486 g->state.blending != SJME_SCRITCHUI_PENCIL_BLEND_SRC);
488 /* Forward. */
489 if (g->impl->setAlphaColor != NULL)
490 return g->impl->setAlphaColor(g, argb);
491 return SJME_ERROR_NONE;
494 sjme_errorCode sjme_scritchpen_core_setBlendingMode(
495 sjme_attrInNotNull sjme_scritchui_pencil g,
496 sjme_attrInRange(0, SJME_NUM_SCRITCHUI_PENCIL_BLENDS)
497 sjme_scritchui_pencilBlendingMode mode)
499 sjme_scritchui_pencilColor* color;
501 if (g == NULL)
502 return SJME_ERROR_NULL_ARGUMENTS;
504 if (mode < 0 || mode >= SJME_NUM_SCRITCHUI_PENCIL_BLENDS)
505 return SJME_ERROR_INVALID_ARGUMENT;
507 /* Source blending cannot be used if there is no alpha channel. */
508 if (!g->hasAlpha && mode == SJME_SCRITCHUI_PENCIL_BLEND_SRC)
509 return SJME_ERROR_INVALID_ARGUMENT;
511 /* Set mode. */
512 g->state.blending = mode;
514 /* Set color again, to reset alpha blending state. */
515 color = &g->state.color;
516 g->api->setAlphaColor(g,
517 (color->a << 24) | (color->r << 16) | (color->g << 8) |
518 color->b);
520 /* Forward. */
521 if (g->impl->setBlendingMode != NULL)
522 return g->impl->setBlendingMode(g, mode);
523 return SJME_ERROR_NONE;
526 sjme_errorCode sjme_scritchpen_core_setClip(
527 sjme_attrInNotNull sjme_scritchui_pencil g,
528 sjme_attrInValue sjme_jint x,
529 sjme_attrInValue sjme_jint y,
530 sjme_attrInPositive sjme_jint w,
531 sjme_attrInPositive sjme_jint h)
533 sjme_scritchui_rect* rect;
534 sjme_scritchui_line* line;
535 sjme_jint ex, ey;
537 if (g == NULL)
538 return SJME_ERROR_NULL_ARGUMENTS;
540 /* Translate coordinates. */
541 sjme_scritchpen_coreUtil_applyTranslate(g, &x, &y);
543 /* Minimum bounds. */
544 if (w <= 0)
545 w = 1;
546 if (h <= 0)
547 h = 1;
549 /* Get actual coordinates of clip end. */
550 ex = x + w;
551 ey = y + h;
553 /* If the clip is negative, normalize to zero. */
554 if (x < 0)
555 x = 0;
556 if (y < 0)
557 y = 0;
559 /* If the clip exceeds the buffer bounds, clip it. */
560 if (ex > g->width)
561 ex = g->width;
562 if (ey > g->height)
563 ey = g->height;
565 /* Translate back. */
566 w = ex - x;
567 h = ey - y;
569 /* Copy clip. */
570 rect = &g->state.clip;
571 rect->s.x = x;
572 rect->s.y = y;
573 rect->d.width = w;
574 rect->d.height = h;
576 /* Set end coordinates. */
577 line = &g->state.clipLine;
578 line->s.x = x;
579 line->s.y = y;
580 line->e.x = ex;
581 line->e.y = ey;
583 /* Forward to native call. */
584 if (g->impl->setClip != NULL)
585 return g->impl->setClip(g, x, y, w, h);
586 return SJME_ERROR_NONE;
589 sjme_errorCode sjme_scritchpen_core_setDefaultFont(
590 sjme_attrInNotNull sjme_scritchui_pencil g)
592 sjme_errorCode error;
594 if (g == NULL)
595 return SJME_ERROR_NULL_ARGUMENTS;
597 /* Reset to use the default font. */
598 g->state.font = g->defaultFont;
600 /* Success! */
601 return SJME_ERROR_NONE;
604 sjme_errorCode sjme_scritchpen_core_setParametersFrom(
605 sjme_attrInNotNull sjme_scritchui_pencil g,
606 sjme_attrInNotNull sjme_scritchui_pencil from)
608 sjme_errorCode error;
610 if (g == NULL || from == NULL)
611 return SJME_ERROR_NONE;
613 /* Initially successful. */
614 error = SJME_ERROR_NONE;
616 /* Remove any current translation. */
617 error |= g->api->translate(g,
618 -g->state.translate.x, -g->state.translate.y);
620 /* Copy all basic parameters. */
621 error |= g->api->setAlphaColor(g, from->state.color.argb);
622 error |= g->api->setClip(g, from->state.clip.s.x, from->state.clip.s.y,
623 from->state.clip.d.width, from->state.clip.d.height);
624 error |= g->api->setStrokeStyle(g, from->state.stroke);
626 /* We can only copy the blending mode if we have alpha support. */
627 if (!g->hasAlpha)
628 error |= g->api->setBlendingMode(g,
629 SJME_SCRITCHUI_PENCIL_BLEND_SRC_OVER);
630 else
631 error |= g->api->setBlendingMode(g, from->state.blending);
633 /* If the other has no font, then just set the default. */
634 if (from->state.font == NULL)
635 error |= g->api->setDefaultFont(g);
636 else
637 error |= g->api->setFont(g, from->state.font);
639 /* Re-translate to target coordinate system. */
640 error |= g->api->translate(g,
641 from->state.translate.x, from->state.translate.y);
643 /* Any resultant error? */
644 return error;
647 sjme_errorCode sjme_scritchpen_core_setStrokeStyle(
648 sjme_attrInNotNull sjme_scritchui_pencil g,
649 sjme_attrInRange(0, SJME_NUM_SCRITCHUI_PENCIL_STROKES)
650 sjme_scritchui_pencilStrokeMode style)
652 if (g == NULL)
653 return SJME_ERROR_NULL_ARGUMENTS;
655 if (style < 0 || style >= SJME_NUM_SCRITCHUI_PENCIL_STROKES)
656 return SJME_ERROR_INVALID_ARGUMENT;
658 /* Set stroke mode. */
659 g->state.stroke = style;
661 /* Forward to native. */
662 if (g->impl->setStrokeStyle != NULL)
663 return g->impl->setStrokeStyle(g, style);
664 return SJME_ERROR_NONE;
667 sjme_errorCode sjme_scritchpen_core_translate(
668 sjme_attrInNotNull sjme_scritchui_pencil g,
669 sjme_attrInValue sjme_jint x,
670 sjme_attrInValue sjme_jint y)
672 if (g == NULL)
673 return SJME_ERROR_NULL_ARGUMENTS;
675 /* Add to the translation. */
676 g->state.translate.x += x;
677 g->state.translate.y += y;
679 /* Success! */
680 return SJME_ERROR_NONE;