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 "lib/scritchui/framebuffer/fb.h"
13 #include "lib/scritchui/scritchui.h"
14 #include "lib/scritchui/scritchuiTypes.h"
15 #include "lib/scritchui/framebuffer/fbIntern.h"
17 static sjme_errorCode
sjme_scritchui_fb_selLock(
18 sjme_attrInNotNull sjme_scritchui_pencil g
)
21 return SJME_ERROR_NULL_ARGUMENTS
;
23 /* Just directly set the buffer. */
24 g
->lockState
.base
= g
->lockState
.source
.wrapper
;
25 g
->lockState
.baseLimitBytes
= (sjme_jint
)(
26 (sjme_intPointer
)g
->lockState
.source
.data
);
29 return SJME_ERROR_NONE
;
32 static sjme_errorCode
sjme_scritchui_fb_selLockRelease(
33 sjme_attrInNotNull sjme_scritchui_pencil g
)
36 return SJME_ERROR_NULL_ARGUMENTS
;
39 return SJME_ERROR_NONE
;
42 /** Selection buffer functions. */
43 static const sjme_scritchui_pencilLockFunctions sjme_scritchui_fb_selBufFuncs
=
45 .lock
= sjme_scritchui_fb_selLock
,
46 .lockRelease
= sjme_scritchui_fb_selLockRelease
,
49 static sjme_errorCode
sjme_scritchui_fb_eventInput(
50 sjme_attrInNotNull sjme_scritchui wrappedState
,
51 sjme_attrInNotNull sjme_scritchui_uiComponent wrappedComponent
,
52 sjme_attrInNotNull
const sjme_scritchinput_event
* inEvent
)
55 sjme_scritchui inState
;
56 sjme_scritchui_uiComponent inComponent
;
57 sjme_scritchui_fb_widgetState
* wState
;
58 sjme_jint pX
, pY
, selId
;
59 sjme_jboolean hasFocus
, hover
;
60 sjme_scritchinput_key logical
;
62 if (wrappedState
== NULL
|| wrappedComponent
== NULL
|| inEvent
== NULL
)
63 return SJME_ERROR_NULL_ARGUMENTS
;
65 /* Get owning state and component. */
66 inState
= wrappedComponent
->common
.frontEnd
.data
;
67 inComponent
= wrappedComponent
->common
.frontEnd
.wrapper
;
69 if (inState
== NULL
|| inComponent
== NULL
)
70 return SJME_ERROR_NULL_ARGUMENTS
;
72 /* Recover the widget state for this lightweight component. */
73 /* If there is no state yet, then we never rendered this widget. */
74 wState
= inComponent
->common
.handle
[SJME_SUI_FB_H_WSTATE
];
76 return SJME_ERROR_NONE
;
78 /* Is the pointer hovering? */
79 hover
= SJME_JNI_FALSE
;
80 if (inEvent
->type
== SJME_SCRITCHINPUT_TYPE_MOUSE_MOTION
||
81 inEvent
->type
== SJME_SCRITCHINPUT_TYPE_STYLUS_HOVER_MOTION
)
82 hover
= SJME_JNI_TRUE
;
84 /* Pointer event, or we are hovering over something? */
85 if (inEvent
->type
== SJME_SCRITCHINPUT_TYPE_MOUSE_BUTTON_PRESSED
||
86 inEvent
->type
== SJME_SCRITCHINPUT_TYPE_TOUCH_FINGER_PRESSED
||
87 inEvent
->type
== SJME_SCRITCHINPUT_TYPE_STYLUS_PEN_PRESSED
||
90 /* Only change focus if we are not hovering over this. */
93 /* Check if we have focus. */
94 hasFocus
= SJME_JNI_FALSE
;
95 if (sjme_error_is(error
= inState
->api
->componentFocusHas(
96 inState
, inComponent
, &hasFocus
)))
97 return sjme_error_default(error
);
99 /* If we do not have focus, grab it and do nothing else. */
101 return inState
->api
->componentFocusGrab(
102 inState
, inComponent
);
105 /* If there is no selection buffer, we cannot handle press events */
106 /* as we have no idea what we even clicked on. */
107 if (wState
->selBuf
== NULL
)
108 return SJME_ERROR_NONE
;
110 /* Recover pointer coordinates. */
111 pX
= inEvent
->data
.mouseButton
.x
;
112 pY
= inEvent
->data
.mouseButton
.y
;
114 /* Outside the buffer edge? */
115 if (pX
< 0 || pY
< 0 ||
116 pX
>= wState
->selBufWidth
|| pY
>= wState
->selBufHeight
)
117 return SJME_ERROR_NONE
;
119 /* Read the selection id here. */
120 selId
= wState
->selBuf
[(pY
* wState
->selBufWidth
) + pX
] & 0xFFFFFF;
122 /* Was there something here that was clicked? */
123 /* Or are we hovering over an item? */
124 if (selId
!= 0 && wState
->lightClickListener
!= NULL
)
127 return wState
->lightHoverListener(inState
, inComponent
,
130 return wState
->lightClickListener(inState
, inComponent
,
135 return SJME_ERROR_NONE
;
138 /* Key event or button? */
139 else if (inEvent
->type
== SJME_SCRITCHINPUT_TYPE_KEY_PRESSED
||
140 inEvent
->type
== SJME_SCRITCHINPUT_TYPE_GAMEPAD_BUTTON_PRESSED
)
142 /* Get logical key. */
143 logical
= SJME_SCRITCHINPUT_KEY_UNKNOWN
;
144 if (sjme_error_is(error
= inState
->implIntern
->logicalButton(
145 inState
, inEvent
, &logical
)))
146 return sjme_error_default(error
);
148 /* Still unknown? Do nothing then... */
149 if (logical
== SJME_SCRITCHINPUT_KEY_UNKNOWN
)
150 return SJME_ERROR_NONE
;
153 if (logical
== SJME_SCRITCHINPUT_KEY_SPACE
)
155 if (wState
->lightSelectListener
!= NULL
)
156 return wState
->lightSelectListener(inState
, inComponent
);
160 else if (logical
== SJME_SCRITCHINPUT_KEY_ENTER
)
162 if (wState
->lightActivateListener
!= NULL
)
163 return wState
->lightActivateListener(inState
, inComponent
);
169 /* Ignore if not supported. */
170 if (wState
->lightCursorListener
== NULL
)
171 return SJME_ERROR_NONE
;
173 /* Base coordinate. */
177 /* Which direction of movement? */
178 if (logical
== SJME_SCRITCHINPUT_KEY_UP
)
180 else if (logical
== SJME_SCRITCHINPUT_KEY_DOWN
)
182 else if (logical
== SJME_SCRITCHINPUT_KEY_LEFT
)
184 else if (logical
== SJME_SCRITCHINPUT_KEY_RIGHT
)
186 else if (logical
== SJME_SCRITCHINPUT_KEY_HOME
)
191 else if (logical
== SJME_SCRITCHINPUT_KEY_END
)
198 return wState
->lightCursorListener(inState
,
199 inComponent
, pX
, pY
);
204 return SJME_ERROR_NONE
;
207 static sjme_errorCode
sjme_scritchui_fb_intern_makeSelBuf(
208 sjme_attrInNotNull sjme_scritchui inState
,
209 sjme_attrInNotNull sjme_scritchui_uiComponent inComponent
,
210 sjme_attrInNotNull sjme_scritchui_fb_widgetState
* wState
,
211 sjme_attrOutNotNull sjme_scritchui_pencil
* outSg
,
212 sjme_attrInPositiveNonZero sjme_jint cW
,
213 sjme_attrInPositiveNonZero sjme_jint cH
)
215 sjme_errorCode error
;
216 sjme_frontEnd sgFrontEnd
;
217 sjme_jint
* tempSelBuf
;
218 sjme_scritchui_pencil sg
;
221 if (inState
== NULL
|| inComponent
== NULL
|| wState
== NULL
||
223 return SJME_ERROR_NULL_ARGUMENTS
;
225 /* Total component area. */
228 /* Need to allocate new buffer? */
229 if (wState
->selBuf
== NULL
|| wState
->selBufLen
< cT
)
231 /* Delete old buffer. */
232 if (wState
->selBuf
!= NULL
)
233 if (sjme_error_is(error
= sjme_alloc_free(
235 goto fail_freeSelBuf
;
236 wState
->selBuf
= NULL
;
239 if (wState
->selBufPencil
!= NULL
)
240 if (sjme_error_is(error
= sjme_alloc_free(
241 wState
->selBufPencil
)))
242 goto fail_freeSelPencil
;
243 wState
->selBufPencil
= NULL
;
245 /* Clear everything. */
246 wState
->selBufLen
= 0;
247 wState
->selBufWidth
= 0;
248 wState
->selBufHeight
= 0;
250 /* Attempt allocation of new buffer. */
252 if (sjme_error_is(error
= sjme_alloc(inState
->pool
,
253 cT
* sizeof(sjme_jint
), (void**)&tempSelBuf
)) ||
255 goto fail_allocSelBuf
;
257 /* Store for usage. */
258 wState
->selBuf
= tempSelBuf
;
259 wState
->selBufLen
= cT
;
260 wState
->selBufWidth
= cW
;
261 wState
->selBufHeight
= cH
;
264 /* Setup front end to point to the buffer. */
265 memset(&sgFrontEnd
, 0, sizeof(sgFrontEnd
));
266 sgFrontEnd
.data
= (sjme_pointer
)
267 ((sjme_intPointer
)cT
* sizeof(sjme_jint
));
268 sgFrontEnd
.wrapper
= wState
->selBuf
;
270 /* Wrap a pencil over the selection buffer if we have none yet. */
271 sg
= wState
->selBufPencil
;
274 /* Setup buffer drawing. */
275 if (sjme_error_is(inState
->api
->hardwareGraphics(inState
,
277 SJME_GFX_PIXEL_FORMAT_INT_RGB888
,
279 &sjme_scritchui_fb_selBufFuncs
,
282 NULL
)) || sg
== NULL
)
283 goto fail_initSelPen
;
285 /* Cache pencil for future operations. */
286 wState
->selBufPencil
= sg
;
291 return SJME_ERROR_NONE
;
297 return sjme_error_default(error
);
300 sjme_errorCode
sjme_scritchui_fb_intern_lightweightInit(
301 sjme_attrInNotNull sjme_scritchui inState
,
302 sjme_attrInNotNull sjme_scritchui_uiComponent inComponent
,
303 sjme_attrOutNotNull sjme_scritchui_fb_widgetState
** outWState
,
304 sjme_attrInValue sjme_jboolean isInteractive
,
305 sjme_attrInNotNull sjme_scritchui_paintListenerFunc paintListener
)
307 sjme_errorCode error
;
308 sjme_scritchui wrappedState
;
309 sjme_scritchui_uiPanel wrappedPanel
;
310 sjme_scritchui_fb_widgetState
* wState
;
312 if (inState
== NULL
|| inComponent
== NULL
|| paintListener
== NULL
||
314 return SJME_ERROR_NULL_ARGUMENTS
;
316 /* Widget state for interactions. */
318 if (sjme_error_is(error
= sjme_alloc(inState
->pool
,
319 sizeof(*wState
), (void**)&wState
)) || wState
== NULL
)
320 return sjme_error_default(error
);
322 /* Recover wrapped state. */
323 wrappedState
= inState
->wrappedState
;
325 /* Store in state. */
326 inComponent
->common
.handle
[SJME_SUI_FB_H_WSTATE
] = wState
;
328 /* Setup wrapped panel to draw our widget on. */
330 if (sjme_error_is(error
= wrappedState
->api
->panelNew(
331 wrappedState
, &wrappedPanel
)) ||
332 wrappedPanel
== NULL
)
333 return sjme_error_default(error
);
335 /* Map front ends. */
336 if (sjme_error_is(error
= sjme_scritchui_fb_biMap(
337 inState
, SJME_SUI_CAST_COMMON(inComponent
),
338 SJME_SUI_CAST_COMMON(wrappedPanel
))))
339 return sjme_error_default(error
);
341 /* If this is interactive, we need to handle inputs and otherwise. */
344 /* Enable focus on the widget. */
345 if (sjme_error_is(error
= wrappedState
->api
->panelEnableFocus(
346 wrappedState
, wrappedPanel
,
347 SJME_JNI_TRUE
, SJME_JNI_FALSE
)))
348 return sjme_error_default(error
);
350 /* Set listener for events. */
351 if (sjme_error_is(error
=
352 wrappedState
->api
->componentSetInputListener(
354 SJME_SUI_CAST_COMPONENT(wrappedPanel
),
355 sjme_scritchui_fb_eventInput
, NULL
)))
356 return sjme_error_default(error
);
359 /* Set renderer for widget. */
360 if (sjme_error_is(error
=
361 wrappedState
->api
->componentSetPaintListener(
363 SJME_SUI_CAST_COMPONENT(wrappedPanel
),
364 paintListener
, NULL
)))
365 return sjme_error_default(error
);
369 return SJME_ERROR_NONE
;
372 sjme_errorCode
sjme_scritchui_fb_intern_logicalButton(
373 sjme_attrInNotNull sjme_scritchui inState
,
374 sjme_attrInNotNull
const sjme_scritchinput_event
* inEvent
,
375 sjme_attrOutNotNull sjme_scritchinput_key
* outKey
)
377 sjme_scritchinput_key target
;
379 if (inState
== NULL
|| inEvent
== NULL
|| outKey
== NULL
)
380 return SJME_ERROR_NULL_ARGUMENTS
;
383 target
= SJME_SCRITCHINPUT_KEY_UNKNOWN
;
386 if (inEvent
->type
== SJME_SCRITCHINPUT_TYPE_KEY_PRESSED
||
387 inEvent
->type
== SJME_SCRITCHINPUT_TYPE_KEY_RELEASED
)
389 switch (inEvent
->data
.key
.code
)
391 case SJME_SCRITCHINPUT_KEY_VGAME_A
:
392 case SJME_SCRITCHINPUT_KEY_VGAME_B
:
393 case SJME_SCRITCHINPUT_KEY_VGAME_C
:
394 case SJME_SCRITCHINPUT_KEY_VGAME_D
:
395 case SJME_SCRITCHINPUT_KEY_SPACE
:
397 target
= SJME_SCRITCHINPUT_KEY_SPACE
;
400 case SJME_SCRITCHINPUT_KEY_ENTER
:
401 case SJME_SCRITCHINPUT_KEY_VGAME_FIRE
:
402 case SJME_SCRITCHINPUT_KEY_NUMPAD_ENTER
:
406 target
= SJME_SCRITCHINPUT_KEY_ENTER
;
409 case SJME_SCRITCHINPUT_KEY_UP
:
410 case SJME_SCRITCHINPUT_KEY_PAGE_UP
:
411 case SJME_SCRITCHINPUT_KEY_VGAME_UP
:
412 case SJME_SCRITCHINPUT_KEY_NUMPAD_MINUS
:
417 target
= SJME_SCRITCHINPUT_KEY_UP
;
420 case SJME_SCRITCHINPUT_KEY_DOWN
:
421 case SJME_SCRITCHINPUT_KEY_PAGE_DOWN
:
422 case SJME_SCRITCHINPUT_KEY_VGAME_DOWN
:
423 case SJME_SCRITCHINPUT_KEY_NUMPAD_PLUS
:
428 target
= SJME_SCRITCHINPUT_KEY_DOWN
;
431 case SJME_SCRITCHINPUT_KEY_LEFT
:
432 case SJME_SCRITCHINPUT_KEY_VGAME_LEFT
:
433 case SJME_SCRITCHINPUT_KEY_NUMPAD_DIVIDE
:
438 target
= SJME_SCRITCHINPUT_KEY_LEFT
;
441 case SJME_SCRITCHINPUT_KEY_RIGHT
:
442 case SJME_SCRITCHINPUT_KEY_VGAME_RIGHT
:
443 case SJME_SCRITCHINPUT_KEY_NUMPAD_MULTIPLY
:
448 target
= SJME_SCRITCHINPUT_KEY_RIGHT
;
451 case SJME_SCRITCHINPUT_KEY_HOME
:
456 target
= SJME_SCRITCHINPUT_KEY_HOME
;
459 case SJME_SCRITCHINPUT_KEY_END
:
464 target
= SJME_SCRITCHINPUT_KEY_END
;
474 return SJME_ERROR_NONE
;
477 sjme_errorCode
sjme_scritchui_fb_intern_refresh(
478 sjme_attrInNotNull sjme_scritchui inState
,
479 sjme_attrInNotNull sjme_scritchui_uiComponent inComponent
)
481 sjme_errorCode error
;
482 sjme_scritchui wrappedState
;
483 sjme_scritchui_uiComponent wrappedComponent
;
485 if (inState
== NULL
|| inComponent
== NULL
)
486 return SJME_ERROR_NULL_ARGUMENTS
;
488 /* Recover wrapped state. */
489 wrappedState
= inState
->wrappedState
;
491 inComponent
->common
.handle
[SJME_SUI_FB_H_WRAPPED
];
493 /* Request repaint for the wrapped component. */
494 if (sjme_error_is(error
= wrappedState
->api
->componentRevalidate(
495 wrappedState
, wrappedComponent
)))
496 return sjme_error_default(error
);
497 return wrappedState
->api
->componentRepaint(wrappedState
,
499 0, 0, INT32_MAX
, INT32_MAX
);
502 sjme_errorCode
sjme_scritchui_fb_intern_render(
503 sjme_attrInNotNull sjme_scritchui inState
,
504 sjme_attrInNullable sjme_scritchui_uiComponent inComponent
,
505 sjme_attrInNotNull sjme_scritchui_pencil g
,
506 sjme_attrInNotNull
const sjme_scritchui_fb_displayList
* dlFull
,
507 sjme_attrInPositive sjme_jint dlCount
,
508 sjme_attrOutNullable sjme_scritchui_rect
* focusRect
,
509 sjme_attrInNullable
const sjme_scritchui_fb_displayShaders
* shaders
,
510 sjme_attrInNullable sjme_pointer shaderData
)
512 sjme_errorCode error
;
514 sjme_scritchui_fb_widgetState
* wState
;
515 const sjme_scritchui_fb_displayList
* dlAt
;
516 sjme_scritchui_pencil sg
;
517 sjme_jint bsx
, bsy
, bex
, bey
, bw
, bh
;
523 sjme_jint lafColors
[SJME_SCRITCHUI_NUM_LAF_ELEMENT_COLOR
];
524 sjme_scritchui_lafElementColorType colorType
;
525 sjme_scritchui_rect useFocusRect
;
526 sjme_scritchui_dim suggestDim
;
528 if (inState
== NULL
|| g
== NULL
|| dlFull
== NULL
)
529 return SJME_ERROR_NULL_ARGUMENTS
;
531 if (shaderData
!= NULL
&& shaders
== NULL
)
532 return SJME_ERROR_NULL_ARGUMENTS
;
535 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
537 /* Recover widget state, if this has one for selection buffering. */
541 if (inComponent
!= NULL
)
543 /* Recover the widget state for this lightweight component. */
544 wState
= inComponent
->common
.handle
[SJME_SUI_FB_H_WSTATE
];
546 /* Read in component size. */
547 if (sjme_error_is(error
= inState
->api
->componentSize(
548 inState
, inComponent
, &cW
, &cH
)))
549 goto fail_componentSize
;
552 /* If the surface area is too small, stop as nothing can be drawn. */
553 if (cW
<= 0 || cH
<= 0)
554 return SJME_ERROR_NONE
;
556 /* Clear focus rectangle. */
557 memset(&useFocusRect
, 0, sizeof(useFocusRect
));
559 /* Does the selection buffer need initializing? */
562 if (sjme_error_is(error
= sjme_scritchui_fb_intern_makeSelBuf(
563 inState
, inComponent
, wState
, &sg
, cW
, cH
)))
564 goto fail_selBufInit
;
566 /* Initially blank, but becomes the suggested dimension. */
567 memset(&suggestDim
, 0, sizeof(suggestDim
));
569 /* Obtain all the look and feel colors, if any fail fallback to default. */
570 memset(lafColors
, 0, sizeof(lafColors
));
571 for (i
= 0; i
< SJME_SCRITCHUI_NUM_LAF_ELEMENT_COLOR
; i
++)
572 if (sjme_error_is(error
= inState
->apiInThread
->lafElementColor(
573 inState
, inComponent
,
575 lafColors
[i
] = 0xFF000000;
577 /* Perform all drawing operations. */
578 for (dlIndex
= 0; dlIndex
< dlCount
; dlIndex
++)
580 /* Get the item to draw. */
581 dlAt
= &dlFull
[dlIndex
];
584 if (dlAt
->type
== SJME_SCRITCHUI_FB_DL_TYPE_NOTHING
)
587 /* Normalize clip coordinates. */
588 bsx
= dlAt
->bound
.s
.x
;
589 bsy
= dlAt
->bound
.s
.y
;
590 bw
= dlAt
->bound
.d
.width
;
591 bh
= dlAt
->bound
.d
.height
;
595 /* Move suggestion box up. */
596 if (bex
> suggestDim
.width
)
597 suggestDim
.width
= bex
;
598 if (bey
> suggestDim
.height
)
599 suggestDim
.height
= bey
;
601 /* If this is focused, use the bounds of this display list. */
602 if (dlAt
->mod
& SJME_SCRITCHUI_FB_DL_TYPE_MOD_FOCUS
)
604 useFocusRect
.s
.x
= bsx
;
605 useFocusRect
.s
.y
= bsy
;
606 useFocusRect
.d
.width
= bw
;
607 useFocusRect
.d
.height
= bh
;
610 /* Remove old translation. */
611 g
->api
->translate(g
, -g
->state
.translate
.x
, -g
->state
.translate
.y
);
613 /* Set clip bound for the item. */
614 g
->api
->setClip(g
, bsx
, bsy
, bw
, bh
);
616 /* Translate to base coordinates. */
617 g
->api
->translate(g
, bsx
, bsy
);
619 /* Revert back to solid. */
620 g
->api
->setStrokeStyle(g
, SJME_SCRITCHUI_PENCIL_STROKE_SOLID
);
622 /* Set font to use? */
623 if (dlAt
->type
== SJME_SCRITCHUI_FB_DL_TYPE_TEXT
)
624 g
->api
->setFont(g
, dlAt
->data
.text
.font
);
626 /* Determine base color. */
628 if (dlAt
->color
>= 0 &&
629 dlAt
->color
< SJME_SCRITCHUI_NUM_LAF_ELEMENT_COLOR
)
630 colorType
= dlAt
->color
;
632 /* Adjust to highlight color? */
633 if (dlAt
->mod
& SJME_SCRITCHUI_FB_DL_TYPE_MOD_SELECTED
)
635 if (colorType
== SJME_SCRITCHUI_LAF_ELEMENT_COLOR_BACKGROUND
)
637 SJME_SCRITCHUI_LAF_ELEMENT_COLOR_HIGHLIGHTED_BACKGROUND
;
638 else if (colorType
== SJME_SCRITCHUI_LAF_ELEMENT_COLOR_FOREGROUND
)
640 SJME_SCRITCHUI_LAF_ELEMENT_COLOR_HIGHLIGHTED_FOREGROUND
;
641 else if (colorType
== SJME_SCRITCHUI_LAF_ELEMENT_COLOR_BORDER
)
643 SJME_SCRITCHUI_LAF_ELEMENT_COLOR_HIGHLIGHTED_BORDER
;
647 g
->api
->setAlphaColor(g
, lafColors
[colorType
]);
649 /* Must handle drawing of the selection buffer */
650 doSel
= (dlAt
->selection
!= 0);
651 if (sg
!= NULL
&& doSel
)
653 /* Copy all the translation and otherwise here. */
654 if (sjme_error_is(error
= sg
->api
->setParametersFrom(sg
,
656 goto fail_sgCopyParam
;
658 /* The color is the selection index. */
659 if (sjme_error_is(error
= sg
->api
->setAlphaColor(sg
,
660 0xFF000000 | dlAt
->selection
)))
661 goto fail_sgSelColor
;
664 /* Which type is being drawn? */
668 case SJME_SCRITCHUI_FB_DL_TYPE_BOX
:
669 if (dlAt
->mod
& SJME_SCRITCHUI_FB_DL_TYPE_MOD_SELECTED
)
670 g
->api
->fillRect(g
, 0, 0, bw
- 1, bh
- 1);
672 g
->api
->drawRect(g
, 0, 0, bw
- 1, bh
- 1);
674 /* Selection buffer, always filled here! */
675 if (sg
!= NULL
&& doSel
)
676 sg
->api
->fillRect(sg
, 0, 0, bw
- 1, bh
- 1);
680 case SJME_SCRITCHUI_FB_DL_TYPE_TEXT
:
681 if (dlAt
->data
.text
.string
!= NULL
)
683 /* Load in string. */
684 memset(&seq
, 0, sizeof(seq
));
685 if (sjme_error_is(error
= sjme_charSeq_newUtfStatic(
686 &seq
, dlAt
->data
.text
.string
)))
687 goto fail_charSeqLoad
;
689 /* Determine how long the string is. */
691 if (sjme_error_is(error
= sjme_charSeq_length(
693 goto fail_charSeqLen
;
696 g
->api
->drawSubstring(g
, &seq
, 0, seqLen
,
699 /* Selection buffer. */
700 if (sg
!= NULL
&& doSel
)
701 sg
->api
->drawSubstring(sg
, &seq
, 0, seqLen
,
704 /* If disabled, cross it out. */
705 if (dlAt
->mod
& SJME_SCRITCHUI_FB_DL_TYPE_MOD_DISABLED
)
706 g
->api
->drawHoriz(g
, 0, bh
/ 2, bw
);
712 /* Either we pass our focus rectangle up to the caller or we draw it. */
713 if (focusRect
!= NULL
)
714 memmove(focusRect
, &useFocusRect
, sizeof(*focusRect
));
715 else if (useFocusRect
.d
.width
> 0 && useFocusRect
.d
.height
> 0)
717 /* Make sure we can actually draw here. */
718 g
->api
->translate(g
, -g
->state
.translate
.x
, -g
->state
.translate
.y
);
719 g
->api
->setClip(g
, 0, 0, g
->width
, g
->height
);
722 g
->api
->setAlphaColor(g
, lafColors
[
723 SJME_SCRITCHUI_LAF_ELEMENT_COLOR_HIGHLIGHTED_FOREGROUND
]);
724 g
->api
->setStrokeStyle(g
, SJME_SCRITCHUI_PENCIL_STROKE_SOLID
);
726 /* Draw boxes for the focus set. */
727 g
->api
->drawRect(g
, useFocusRect
.s
.x
, useFocusRect
.s
.y
,
728 useFocusRect
.d
.width
- 1, useFocusRect
.d
.height
- 1);
730 /* Make it bright! */
731 g
->api
->setStrokeStyle(g
, SJME_SCRITCHUI_PENCIL_STROKE_DOTTED
);
732 g
->api
->setAlphaColor(g
, lafColors
[
733 SJME_SCRITCHUI_LAF_ELEMENT_COLOR_FOCUS_BORDER
]);
735 /* Draw boxes for the focus set. */
736 g
->api
->drawRect(g
, useFocusRect
.s
.x
, useFocusRect
.s
.y
,
737 useFocusRect
.d
.width
- 1, useFocusRect
.d
.height
- 1);
739 /* Revert back to solid. */
740 g
->api
->setStrokeStyle(g
, SJME_SCRITCHUI_PENCIL_STROKE_SOLID
);
743 /* If we are within a viewport, make a size suggestion from our render! */
744 if (inComponent
!= NULL
)
745 if (sjme_error_is(error
= inState
->intern
->viewSuggest(inState
,
746 inComponent
, &suggestDim
)))
747 return sjme_error_default(error
);
750 return SJME_ERROR_NONE
;
760 sjme_message("FB Render Failed: %d", error
);
762 return sjme_error_default(error
);
765 sjme_errorCode
sjme_scritchui_fb_intern_renderInScroll(
766 sjme_attrInNotNull sjme_scritchui inState
,
767 sjme_attrInNotNull sjme_scritchui_uiComponent inComponent
,
768 sjme_attrInNotNull sjme_scritchui_pencil g
,
769 sjme_attrInNotNull
const sjme_scritchui_fb_displayList
* dlFull
,
770 sjme_attrInPositive sjme_jint dlCount
,
771 sjme_attrInNullable sjme_scritchui_rect
* focusRect
,
772 sjme_attrInNullable
const sjme_scritchui_fb_displayShaders
* shaders
,
773 sjme_attrInNullable sjme_pointer shaderData
)
775 /* For now just ignore this and draw directly on. */
776 return inState
->implIntern
->render(inState
, inComponent
, g
,
777 dlFull
, dlCount
, focusRect
, shaders
, shaderData
);