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
), &tempSelBuf
)) || tempSelBuf
== NULL
)
254 goto fail_allocSelBuf
;
256 /* Store for usage. */
257 wState
->selBuf
= tempSelBuf
;
258 wState
->selBufLen
= cT
;
259 wState
->selBufWidth
= cW
;
260 wState
->selBufHeight
= cH
;
263 /* Setup front end to point to the buffer. */
264 memset(&sgFrontEnd
, 0, sizeof(sgFrontEnd
));
265 sgFrontEnd
.data
= (sjme_pointer
)
266 ((sjme_intPointer
)cT
* sizeof(sjme_jint
));
267 sgFrontEnd
.wrapper
= wState
->selBuf
;
269 /* Wrap a pencil over the selection buffer if we have none yet. */
270 sg
= wState
->selBufPencil
;
273 /* Setup buffer drawing. */
274 if (sjme_error_is(inState
->api
->hardwareGraphics(inState
,
276 SJME_GFX_PIXEL_FORMAT_INT_RGB888
,
278 &sjme_scritchui_fb_selBufFuncs
,
281 NULL
)) || sg
== NULL
)
282 goto fail_initSelPen
;
284 /* Cache pencil for future operations. */
285 wState
->selBufPencil
= sg
;
290 return SJME_ERROR_NONE
;
296 return sjme_error_default(error
);
299 sjme_errorCode
sjme_scritchui_fb_intern_lightweightInit(
300 sjme_attrInNotNull sjme_scritchui inState
,
301 sjme_attrInNotNull sjme_scritchui_uiComponent inComponent
,
302 sjme_attrOutNotNull sjme_scritchui_fb_widgetState
** outWState
,
303 sjme_attrInValue sjme_jboolean isInteractive
,
304 sjme_attrInNotNull sjme_scritchui_paintListenerFunc paintListener
)
306 sjme_errorCode error
;
307 sjme_scritchui wrappedState
;
308 sjme_scritchui_uiPanel wrappedPanel
;
309 sjme_scritchui_fb_widgetState
* wState
;
311 if (inState
== NULL
|| inComponent
== NULL
|| paintListener
== NULL
||
313 return SJME_ERROR_NULL_ARGUMENTS
;
315 /* Widget state for interactions. */
317 if (sjme_error_is(error
= sjme_alloc(inState
->pool
,
318 sizeof(*wState
), &wState
)) || wState
== NULL
)
319 return sjme_error_default(error
);
321 /* Recover wrapped state. */
322 wrappedState
= inState
->wrappedState
;
324 /* Store in state. */
325 inComponent
->common
.handle
[SJME_SUI_FB_H_WSTATE
] = wState
;
327 /* Setup wrapped panel to draw our widget on. */
329 if (sjme_error_is(error
= wrappedState
->api
->panelNew(
330 wrappedState
, &wrappedPanel
)) ||
331 wrappedPanel
== NULL
)
332 return sjme_error_default(error
);
334 /* Map front ends. */
335 if (sjme_error_is(error
= sjme_scritchui_fb_biMap(
336 inState
, inComponent
, wrappedPanel
)))
337 return sjme_error_default(error
);
339 /* If this is interactive, we need to handle inputs and otherwise. */
342 /* Enable focus on the widget. */
343 if (sjme_error_is(error
= wrappedState
->api
->panelEnableFocus(
344 wrappedState
, wrappedPanel
,
345 SJME_JNI_TRUE
, SJME_JNI_FALSE
)))
346 return sjme_error_default(error
);
348 /* Set listener for events. */
349 if (sjme_error_is(error
=
350 wrappedState
->api
->componentSetInputListener(
351 wrappedState
, wrappedPanel
,
352 sjme_scritchui_fb_eventInput
, NULL
)))
353 return sjme_error_default(error
);
356 /* Set renderer for widget. */
357 if (sjme_error_is(error
=
358 wrappedState
->api
->componentSetPaintListener(
359 wrappedState
, wrappedPanel
,
360 paintListener
, NULL
)))
361 return sjme_error_default(error
);
365 return SJME_ERROR_NONE
;
368 sjme_errorCode
sjme_scritchui_fb_intern_logicalButton(
369 sjme_attrInNotNull sjme_scritchui inState
,
370 sjme_attrInNotNull
const sjme_scritchinput_event
* inEvent
,
371 sjme_attrOutNotNull sjme_scritchinput_key
* outKey
)
373 sjme_scritchinput_key target
;
375 if (inState
== NULL
|| inEvent
== NULL
|| outKey
== NULL
)
376 return SJME_ERROR_NULL_ARGUMENTS
;
379 target
= SJME_SCRITCHINPUT_KEY_UNKNOWN
;
382 if (inEvent
->type
== SJME_SCRITCHINPUT_TYPE_KEY_PRESSED
||
383 inEvent
->type
== SJME_SCRITCHINPUT_TYPE_KEY_RELEASED
)
385 switch (inEvent
->data
.key
.code
)
387 case SJME_SCRITCHINPUT_KEY_VGAME_A
:
388 case SJME_SCRITCHINPUT_KEY_VGAME_B
:
389 case SJME_SCRITCHINPUT_KEY_VGAME_C
:
390 case SJME_SCRITCHINPUT_KEY_VGAME_D
:
391 case SJME_SCRITCHINPUT_KEY_SPACE
:
393 target
= SJME_SCRITCHINPUT_KEY_SPACE
;
396 case SJME_SCRITCHINPUT_KEY_ENTER
:
397 case SJME_SCRITCHINPUT_KEY_VGAME_FIRE
:
398 case SJME_SCRITCHINPUT_KEY_NUMPAD_ENTER
:
402 target
= SJME_SCRITCHINPUT_KEY_ENTER
;
405 case SJME_SCRITCHINPUT_KEY_UP
:
406 case SJME_SCRITCHINPUT_KEY_PAGE_UP
:
407 case SJME_SCRITCHINPUT_KEY_VGAME_UP
:
408 case SJME_SCRITCHINPUT_KEY_NUMPAD_MINUS
:
413 target
= SJME_SCRITCHINPUT_KEY_UP
;
416 case SJME_SCRITCHINPUT_KEY_DOWN
:
417 case SJME_SCRITCHINPUT_KEY_PAGE_DOWN
:
418 case SJME_SCRITCHINPUT_KEY_VGAME_DOWN
:
419 case SJME_SCRITCHINPUT_KEY_NUMPAD_PLUS
:
424 target
= SJME_SCRITCHINPUT_KEY_DOWN
;
427 case SJME_SCRITCHINPUT_KEY_LEFT
:
428 case SJME_SCRITCHINPUT_KEY_VGAME_LEFT
:
429 case SJME_SCRITCHINPUT_KEY_NUMPAD_DIVIDE
:
434 target
= SJME_SCRITCHINPUT_KEY_LEFT
;
437 case SJME_SCRITCHINPUT_KEY_RIGHT
:
438 case SJME_SCRITCHINPUT_KEY_VGAME_RIGHT
:
439 case SJME_SCRITCHINPUT_KEY_NUMPAD_MULTIPLY
:
444 target
= SJME_SCRITCHINPUT_KEY_RIGHT
;
447 case SJME_SCRITCHINPUT_KEY_HOME
:
452 target
= SJME_SCRITCHINPUT_KEY_HOME
;
455 case SJME_SCRITCHINPUT_KEY_END
:
460 target
= SJME_SCRITCHINPUT_KEY_END
;
470 return SJME_ERROR_NONE
;
473 sjme_errorCode
sjme_scritchui_fb_intern_refresh(
474 sjme_attrInNotNull sjme_scritchui inState
,
475 sjme_attrInNotNull sjme_scritchui_uiComponent inComponent
)
477 sjme_errorCode error
;
478 sjme_scritchui wrappedState
;
479 sjme_scritchui_uiComponent wrappedComponent
;
481 if (inState
== NULL
|| inComponent
== NULL
)
482 return SJME_ERROR_NULL_ARGUMENTS
;
484 /* Recover wrapped state. */
485 wrappedState
= inState
->wrappedState
;
487 inComponent
->common
.handle
[SJME_SUI_FB_H_WRAPPED
];
489 /* Request repaint for the wrapped component. */
490 if (sjme_error_is(error
= wrappedState
->api
->componentRevalidate(
491 wrappedState
, wrappedComponent
)))
492 return sjme_error_default(error
);
493 return wrappedState
->api
->componentRepaint(wrappedState
,
495 0, 0, INT32_MAX
, INT32_MAX
);
498 sjme_errorCode
sjme_scritchui_fb_intern_render(
499 sjme_attrInNotNull sjme_scritchui inState
,
500 sjme_attrInNullable sjme_scritchui_uiComponent inComponent
,
501 sjme_attrInNotNull sjme_scritchui_pencil g
,
502 sjme_attrInNotNull
const sjme_scritchui_fb_displayList
* dlFull
,
503 sjme_attrInPositive sjme_jint dlCount
,
504 sjme_attrOutNullable sjme_scritchui_rect
* focusRect
,
505 sjme_attrInNullable
const sjme_scritchui_fb_displayShaders
* shaders
,
506 sjme_attrInNullable sjme_pointer shaderData
)
508 sjme_errorCode error
;
510 sjme_scritchui_fb_widgetState
* wState
;
511 const sjme_scritchui_fb_displayList
* dlAt
;
512 sjme_scritchui_pencil sg
;
513 sjme_jint bsx
, bsy
, bex
, bey
, bw
, bh
;
519 sjme_jint lafColors
[SJME_SCRITCHUI_NUM_LAF_ELEMENT_COLOR
];
520 sjme_scritchui_lafElementColorType colorType
;
521 sjme_scritchui_rect useFocusRect
;
522 sjme_scritchui_dim suggestDim
;
524 if (inState
== NULL
|| g
== NULL
|| dlFull
== NULL
)
525 return SJME_ERROR_NULL_ARGUMENTS
;
527 if (shaderData
!= NULL
&& shaders
== NULL
)
528 return SJME_ERROR_NULL_ARGUMENTS
;
531 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
533 /* Recover widget state, if this has one for selection buffering. */
537 if (inComponent
!= NULL
)
539 /* Recover the widget state for this lightweight component. */
540 wState
= inComponent
->common
.handle
[SJME_SUI_FB_H_WSTATE
];
542 /* Read in component size. */
543 if (sjme_error_is(error
= inState
->api
->componentSize(
544 inState
, inComponent
, &cW
, &cH
)))
545 goto fail_componentSize
;
548 /* If the surface area is too small, stop as nothing can be drawn. */
549 if (cW
<= 0 || cH
<= 0)
550 return SJME_ERROR_NONE
;
552 /* Clear focus rectangle. */
553 memset(&useFocusRect
, 0, sizeof(useFocusRect
));
555 /* Does the selection buffer need initializing? */
558 if (sjme_error_is(error
= sjme_scritchui_fb_intern_makeSelBuf(
559 inState
, inComponent
, wState
, &sg
, cW
, cH
)))
560 goto fail_selBufInit
;
562 /* Initially blank, but becomes the suggested dimension. */
563 memset(&suggestDim
, 0, sizeof(suggestDim
));
565 /* Obtain all the look and feel colors, if any fail fallback to default. */
566 memset(lafColors
, 0, sizeof(lafColors
));
567 for (i
= 0; i
< SJME_SCRITCHUI_NUM_LAF_ELEMENT_COLOR
; i
++)
568 if (sjme_error_is(error
= inState
->apiInThread
->lafElementColor(
569 inState
, inComponent
,
571 lafColors
[i
] = 0xFF000000;
573 /* Perform all drawing operations. */
574 for (dlIndex
= 0; dlIndex
< dlCount
; dlIndex
++)
576 /* Get the item to draw. */
577 dlAt
= &dlFull
[dlIndex
];
580 if (dlAt
->type
== SJME_SCRITCHUI_FB_DL_TYPE_NOTHING
)
583 /* Normalize clip coordinates. */
584 bsx
= dlAt
->bound
.s
.x
;
585 bsy
= dlAt
->bound
.s
.y
;
586 bw
= dlAt
->bound
.d
.width
;
587 bh
= dlAt
->bound
.d
.height
;
591 /* Move suggestion box up. */
592 if (bex
> suggestDim
.width
)
593 suggestDim
.width
= bex
;
594 if (bey
> suggestDim
.height
)
595 suggestDim
.height
= bey
;
597 /* If this is focused, use the bounds of this display list. */
598 if (dlAt
->mod
& SJME_SCRITCHUI_FB_DL_TYPE_MOD_FOCUS
)
600 useFocusRect
.s
.x
= bsx
;
601 useFocusRect
.s
.y
= bsy
;
602 useFocusRect
.d
.width
= bw
;
603 useFocusRect
.d
.height
= bh
;
606 /* Remove old translation. */
607 g
->api
->translate(g
, -g
->state
.translate
.x
, -g
->state
.translate
.y
);
609 /* Set clip bound for the item. */
610 g
->api
->setClip(g
, bsx
, bsy
, bw
, bh
);
612 /* Translate to base coordinates. */
613 g
->api
->translate(g
, bsx
, bsy
);
615 /* Revert back to solid. */
616 g
->api
->setStrokeStyle(g
, SJME_SCRITCHUI_PENCIL_STROKE_SOLID
);
618 /* Set font to use? */
619 if (dlAt
->type
== SJME_SCRITCHUI_FB_DL_TYPE_TEXT
)
620 g
->api
->setFont(g
, dlAt
->data
.text
.font
);
622 /* Determine base color. */
624 if (dlAt
->color
>= 0 &&
625 dlAt
->color
< SJME_SCRITCHUI_NUM_LAF_ELEMENT_COLOR
)
626 colorType
= dlAt
->color
;
628 /* Adjust to highlight color? */
629 if (dlAt
->mod
& SJME_SCRITCHUI_FB_DL_TYPE_MOD_SELECTED
)
631 if (colorType
== SJME_SCRITCHUI_LAF_ELEMENT_COLOR_BACKGROUND
)
633 SJME_SCRITCHUI_LAF_ELEMENT_COLOR_HIGHLIGHTED_BACKGROUND
;
634 else if (colorType
== SJME_SCRITCHUI_LAF_ELEMENT_COLOR_FOREGROUND
)
636 SJME_SCRITCHUI_LAF_ELEMENT_COLOR_HIGHLIGHTED_FOREGROUND
;
637 else if (colorType
== SJME_SCRITCHUI_LAF_ELEMENT_COLOR_BORDER
)
639 SJME_SCRITCHUI_LAF_ELEMENT_COLOR_HIGHLIGHTED_BORDER
;
643 g
->api
->setAlphaColor(g
, lafColors
[colorType
]);
645 /* Must handle drawing of the selection buffer */
646 doSel
= (dlAt
->selection
!= 0);
647 if (sg
!= NULL
&& doSel
)
649 /* Copy all the translation and otherwise here. */
650 if (sjme_error_is(error
= sg
->api
->setParametersFrom(sg
,
652 goto fail_sgCopyParam
;
654 /* The color is the selection index. */
655 if (sjme_error_is(error
= sg
->api
->setAlphaColor(sg
,
656 0xFF000000 | dlAt
->selection
)))
657 goto fail_sgSelColor
;
660 /* Which type is being drawn? */
664 case SJME_SCRITCHUI_FB_DL_TYPE_BOX
:
665 if (dlAt
->mod
& SJME_SCRITCHUI_FB_DL_TYPE_MOD_SELECTED
)
666 g
->api
->fillRect(g
, 0, 0, bw
- 1, bh
- 1);
668 g
->api
->drawRect(g
, 0, 0, bw
- 1, bh
- 1);
670 /* Selection buffer, always filled here! */
671 if (sg
!= NULL
&& doSel
)
672 sg
->api
->fillRect(sg
, 0, 0, bw
- 1, bh
- 1);
676 case SJME_SCRITCHUI_FB_DL_TYPE_TEXT
:
677 if (dlAt
->data
.text
.string
!= NULL
)
679 /* Load in string. */
680 memset(&seq
, 0, sizeof(seq
));
681 if (sjme_error_is(error
= sjme_charSeq_newUtfStatic(
682 &seq
, dlAt
->data
.text
.string
)))
683 goto fail_charSeqLoad
;
685 /* Determine how long the string is. */
687 if (sjme_error_is(error
= sjme_charSeq_length(
689 goto fail_charSeqLen
;
692 g
->api
->drawSubstring(g
, &seq
, 0, seqLen
,
695 /* Selection buffer. */
696 if (sg
!= NULL
&& doSel
)
697 sg
->api
->drawSubstring(sg
, &seq
, 0, seqLen
,
700 /* If disabled, cross it out. */
701 if (dlAt
->mod
& SJME_SCRITCHUI_FB_DL_TYPE_MOD_DISABLED
)
702 g
->api
->drawHoriz(g
, 0, bh
/ 2, bw
);
708 /* Either we pass our focus rectangle up to the caller or we draw it. */
709 if (focusRect
!= NULL
)
710 memmove(focusRect
, &useFocusRect
, sizeof(*focusRect
));
711 else if (useFocusRect
.d
.width
> 0 && useFocusRect
.d
.height
> 0)
713 /* Make sure we can actually draw here. */
714 g
->api
->translate(g
, -g
->state
.translate
.x
, -g
->state
.translate
.y
);
715 g
->api
->setClip(g
, 0, 0, g
->width
, g
->height
);
718 g
->api
->setAlphaColor(g
, lafColors
[
719 SJME_SCRITCHUI_LAF_ELEMENT_COLOR_HIGHLIGHTED_FOREGROUND
]);
720 g
->api
->setStrokeStyle(g
, SJME_SCRITCHUI_PENCIL_STROKE_SOLID
);
722 /* Draw boxes for the focus set. */
723 g
->api
->drawRect(g
, useFocusRect
.s
.x
, useFocusRect
.s
.y
,
724 useFocusRect
.d
.width
- 1, useFocusRect
.d
.height
- 1);
726 /* Make it bright! */
727 g
->api
->setStrokeStyle(g
, SJME_SCRITCHUI_PENCIL_STROKE_DOTTED
);
728 g
->api
->setAlphaColor(g
, lafColors
[
729 SJME_SCRITCHUI_LAF_ELEMENT_COLOR_FOCUS_BORDER
]);
731 /* Draw boxes for the focus set. */
732 g
->api
->drawRect(g
, useFocusRect
.s
.x
, useFocusRect
.s
.y
,
733 useFocusRect
.d
.width
- 1, useFocusRect
.d
.height
- 1);
735 /* Revert back to solid. */
736 g
->api
->setStrokeStyle(g
, SJME_SCRITCHUI_PENCIL_STROKE_SOLID
);
739 /* If we are within a viewport, make a size suggestion from our render! */
740 if (inComponent
!= NULL
)
741 if (sjme_error_is(error
= inState
->intern
->viewSuggest(inState
,
742 inComponent
, &suggestDim
)))
743 return sjme_error_default(error
);
746 return SJME_ERROR_NONE
;
756 sjme_message("FB Render Failed: %d", error
);
758 return sjme_error_default(error
);
761 sjme_errorCode
sjme_scritchui_fb_intern_renderInScroll(
762 sjme_attrInNotNull sjme_scritchui inState
,
763 sjme_attrInNotNull sjme_scritchui_uiComponent inComponent
,
764 sjme_attrInNotNull sjme_scritchui_pencil g
,
765 sjme_attrInNotNull
const sjme_scritchui_fb_displayList
* dlFull
,
766 sjme_attrInPositive sjme_jint dlCount
,
767 sjme_attrInNullable sjme_scritchui_rect
* focusRect
,
768 sjme_attrInNullable
const sjme_scritchui_fb_displayShaders
* shaders
,
769 sjme_attrInNullable sjme_pointer shaderData
)
771 /* For now just ignore this and draw directly on. */
772 return inState
->implIntern
->render(inState
, inComponent
, g
,
773 dlFull
, dlCount
, focusRect
, shaders
, shaderData
);