*/ static void Detach_Gob(REBGOB *gob) /* ** Remove a gob value from its parent. ** Done normally in advance of inserting gobs into new parent. ** ***********************************************************************/ { REBGOB *par; REBINT i; par = GOB_PARENT(gob); if (par && GOB_PANE(par) && (i = Find_Gob(par, gob)) != NOT_FOUND) { Remove_Series(GOB_PANE(par), i, 1); } GOB_PARENT(gob) = 0; }
*/ REBINT PD_Gob(REBPVS *pvs) /* ***********************************************************************/ { REBGOB *gob = VAL_GOB(pvs->value); REBCNT index; REBCNT tail; if (IS_WORD(pvs->select)) { if (pvs->setval == 0 || NOT_END(pvs->path+1)) { if (!Get_GOB_Var(gob, pvs->select, pvs->store)) return PE_BAD_SELECT; // Check for SIZE/X: types of cases: if (pvs->setval && IS_PAIR(pvs->store)) { REBVAL *sel = pvs->select; pvs->value = pvs->store; Next_Path(pvs); // sets value in pvs->store Set_GOB_Var(gob, sel, pvs->store); // write it back to gob } return PE_USE; } else { if (!Set_GOB_Var(gob, pvs->select, pvs->setval)) return PE_BAD_SET; return PE_OK; } } if (IS_INTEGER(pvs->select)) { if (!GOB_PANE(gob)) return PE_NONE; tail = GOB_PANE(gob) ? GOB_TAIL(gob) : 0; index = VAL_GOB_INDEX(pvs->value); index += Int32(pvs->select) - 1; if (index >= tail) return PE_NONE; gob = *GOB_SKIP(gob, index); index = 0; VAL_SET(pvs->store, REB_GOB); VAL_GOB(pvs->store) = gob; VAL_GOB_INDEX(pvs->store) = 0; return PE_USE; } return PE_BAD_SELECT; }
*/ static void Remove_Gobs(REBGOB *gob, REBCNT index, REBCNT len) /* ** Remove one or more gobs from a pane at the given index. ** ***********************************************************************/ { REBGOB **ptr; REBCNT n; ptr = GOB_SKIP(gob, index); for (n = 0; n < len; n++, ptr++) { GOB_PARENT(*ptr) = 0; } Remove_Series(GOB_PANE(gob), index, len); }
*/ REBFLG Find_Gob_Tree(REBGOB *gob, REBGOB *tgob) /* ** Scan a gob tree for the target gob. Return true or false. ** Gob MUST have a pane (check for it first). ** ***********************************************************************/ { REBGOB **gp; REBINT n; gp = GOB_HEAD(gob); for (n = GOB_TAIL(gob); n > 0; n--, gp++) { if (*gp == tgob) return TRUE; if (GOB_PANE(*gp) && Find_Gob_Tree(*gp, tgob)) return TRUE; } return FALSE; }
*/ static REBCNT Find_Gob(REBGOB *gob, REBGOB *target) /* ** Find a target GOB within the pane of another gob. ** Return the index, or a -1 if not found. ** ***********************************************************************/ { REBCNT len; REBCNT n; REBGOB **ptr; if (GOB_PANE(gob)) { len = GOB_TAIL(gob); ptr = GOB_HEAD(gob); for (n = 0; n < len; n++, ptr++) if (*ptr == target) return n; } return NOT_FOUND; }
*/ static REBGOB *Map_Gob_Inner(REBGOB *gob, REBXYF *offset) /* ** Map a higher level gob coordinate to a lower level. ** Returns GOB and sets new offset pair. ** ***********************************************************************/ { REBD32 xo = offset->x; REBD32 yo = offset->y; REBINT n; REBINT len; REBGOB **gop; REBD32 x = 0; REBD32 y = 0; REBINT max_depth = 1000; // avoid infinite loops while (GOB_PANE(gob) && (max_depth-- > 0)) { len = GOB_TAIL(gob); gop = GOB_HEAD(gob) + len - 1; for (n = 0; n < len; n++, gop--) { if ( (xo >= x + GOB_X(*gop)) && (xo < x + GOB_X(*gop) + GOB_W(*gop)) && (yo >= y + GOB_Y(*gop)) && (yo < y + GOB_Y(*gop) + GOB_H(*gop)) ){ x += GOB_X(*gop); y += GOB_Y(*gop); gob = *gop; break; } } if (n >= len) break; // not found } offset->x -= x; offset->y -= y; return gob; }
*/ static REBFLG Get_GOB_Var(REBGOB *gob, REBVAL *word, REBVAL *val) /* ***********************************************************************/ { switch (VAL_WORD_CANON(word)) { case SYM_OFFSET: SET_PAIR(val, GOB_X(gob), GOB_Y(gob)); break; case SYM_SIZE: SET_PAIR(val, GOB_W(gob), GOB_H(gob)); break; case SYM_IMAGE: if (GOB_TYPE(gob) == GOBT_IMAGE) { // image } else goto is_none; break; case SYM_DRAW: if (GOB_TYPE(gob) == GOBT_DRAW) { Set_Block(val, GOB_CONTENT(gob)); // Note: compiler optimizes SET_BLOCKs below } else goto is_none; break; case SYM_TEXT: if (GOB_TYPE(gob) == GOBT_TEXT) { Set_Block(val, GOB_CONTENT(gob)); } else if (GOB_TYPE(gob) == GOBT_STRING) { Set_String(val, GOB_CONTENT(gob)); } else goto is_none; break; case SYM_EFFECT: if (GOB_TYPE(gob) == GOBT_EFFECT) { Set_Block(val, GOB_CONTENT(gob)); } else goto is_none; break; case SYM_COLOR: if (GOB_TYPE(gob) == GOBT_COLOR) { Set_Tuple_Pixel((REBYTE*)&GOB_CONTENT(gob), val); } else goto is_none; break; case SYM_ALPHA: SET_INTEGER(val, GOB_ALPHA(gob)); break; case SYM_PANE: if (GOB_PANE(gob)) Set_Block(val, Pane_To_Block(gob, 0, -1)); else Set_Block(val, Make_Block(0)); break; case SYM_PARENT: if (GOB_PARENT(gob)) { SET_GOB(val, GOB_PARENT(gob)); } else is_none: SET_NONE(val); break; case SYM_DATA: if (GOB_DTYPE(gob) == GOBD_OBJECT) { SET_OBJECT(val, GOB_DATA(gob)); } else if (GOB_DTYPE(gob) == GOBD_BLOCK) { Set_Block(val, GOB_DATA(gob)); } else if (GOB_DTYPE(gob) == GOBD_STRING) { Set_String(val, GOB_DATA(gob)); } else if (GOB_DTYPE(gob) == GOBD_BINARY) { SET_BINARY(val, GOB_DATA(gob)); } else if (GOB_DTYPE(gob) == GOBD_INTEGER) { SET_INTEGER(val, (REBIPT)GOB_DATA(gob)); } else goto is_none; break; case SYM_FLAGS: Set_Block(val, Flags_To_Block(gob)); break; default: return FALSE; } return TRUE; }
*/ static REBFLG Set_GOB_Var(REBGOB *gob, REBVAL *word, REBVAL *val) /* ***********************************************************************/ { switch (VAL_WORD_CANON(word)) { case SYM_OFFSET: return Set_Pair(&(gob->offset), val); case SYM_SIZE: return Set_Pair(&gob->size, val); case SYM_IMAGE: CLR_GOB_OPAQUE(gob); if (IS_IMAGE(val)) { SET_GOB_TYPE(gob, GOBT_IMAGE); GOB_W(gob) = (REBD32)VAL_IMAGE_WIDE(val); GOB_H(gob) = (REBD32)VAL_IMAGE_HIGH(val); GOB_CONTENT(gob) = VAL_SERIES(val); // if (!VAL_IMAGE_TRANSP(val)) SET_GOB_OPAQUE(gob); } else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE); else return FALSE; break; case SYM_DRAW: CLR_GOB_OPAQUE(gob); if (IS_BLOCK(val)) { SET_GOB_TYPE(gob, GOBT_DRAW); GOB_CONTENT(gob) = VAL_SERIES(val); } else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE); else return FALSE; break; case SYM_TEXT: CLR_GOB_OPAQUE(gob); if (IS_BLOCK(val)) { SET_GOB_TYPE(gob, GOBT_TEXT); GOB_CONTENT(gob) = VAL_SERIES(val); } else if (IS_STRING(val)) { SET_GOB_TYPE(gob, GOBT_STRING); GOB_CONTENT(gob) = VAL_SERIES(val); } else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE); else return FALSE; break; case SYM_EFFECT: CLR_GOB_OPAQUE(gob); if (IS_BLOCK(val)) { SET_GOB_TYPE(gob, GOBT_EFFECT); GOB_CONTENT(gob) = VAL_SERIES(val); } else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE); else return FALSE; break; case SYM_COLOR: CLR_GOB_OPAQUE(gob); if (IS_TUPLE(val)) { SET_GOB_TYPE(gob, GOBT_COLOR); Set_Pixel_Tuple((REBYTE*)&GOB_CONTENT(gob), val); if (VAL_TUPLE_LEN(val) < 4 || VAL_TUPLE(val)[3] == 0) SET_GOB_OPAQUE(gob); } else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE); break; case SYM_PANE: if (GOB_PANE(gob)) Clear_Series(GOB_PANE(gob)); if (IS_BLOCK(val)) Insert_Gobs(gob, VAL_BLK_DATA(val), 0, VAL_BLK_LEN(val), 0); else if (IS_GOB(val)) Insert_Gobs(gob, val, 0, 1, 0); else if (IS_NONE(val)) gob->pane = 0; else return FALSE; break; case SYM_ALPHA: GOB_ALPHA(gob) = Clip_Int(Int32(val), 0, 255); break; case SYM_DATA: SET_GOB_DTYPE(gob, GOBD_NONE); if (IS_OBJECT(val)) { SET_GOB_DTYPE(gob, GOBD_OBJECT); SET_GOB_DATA(gob, VAL_OBJ_FRAME(val)); } else if (IS_BLOCK(val)) { SET_GOB_DTYPE(gob, GOBD_BLOCK); SET_GOB_DATA(gob, VAL_SERIES(val)); } else if (IS_STRING(val)) { SET_GOB_DTYPE(gob, GOBD_STRING); SET_GOB_DATA(gob, VAL_SERIES(val)); } else if (IS_BINARY(val)) { SET_GOB_DTYPE(gob, GOBD_BINARY); SET_GOB_DATA(gob, VAL_SERIES(val)); } else if (IS_INTEGER(val)) { SET_GOB_DTYPE(gob, GOBD_INTEGER); SET_GOB_DATA(gob, (void*)(REBIPT)VAL_INT64(val)); } else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE); else return FALSE; break; case SYM_FLAGS: if (IS_WORD(val)) Set_Gob_Flag(gob, val); else if (IS_BLOCK(val)) { gob->flags = 0; for (val = VAL_BLK(val); NOT_END(val); val++) { if (IS_WORD(val)) Set_Gob_Flag(gob, val); } } break; case SYM_OWNER: if (IS_GOB(val)) GOB_TMP_OWNER(gob) = VAL_GOB(val); else return FALSE; break; default: return FALSE; } return TRUE; }
*/ static void Insert_Gobs(REBGOB *gob, REBVAL *arg, REBCNT index, REBCNT len, REBFLG change) /* ** Insert one or more gobs into a pane at the given index. ** If index >= tail, an append occurs. Each gob has its parent ** gob field set. (Call Detach_Gobs() before inserting.) ** ***********************************************************************/ { REBGOB **ptr; REBCNT n, count; REBVAL *val, *sarg; REBINT i; // Verify they are gobs: sarg = arg; for (n = count = 0; n < len; n++, val++) { val = arg++; if (IS_WORD(val)) val = Get_Var(val); if (IS_GOB(val)) { count++; if (GOB_PARENT(VAL_GOB(val))) { // Check if inserting into same parent: i = -1; if (GOB_PARENT(VAL_GOB(val)) == gob) { i = Find_Gob(gob, VAL_GOB(val)); if (i > 0 && i == (REBINT)index-1) { // a no-op SET_GOB_STATE(VAL_GOB(val), GOBS_NEW); return; } } Detach_Gob(VAL_GOB(val)); if ((REBINT)index > i) index--; } } } arg = sarg; // Create or expand the pane series: if (!GOB_PANE(gob)) { GOB_PANE(gob) = Make_Series(count, sizeof(REBGOB*), 0); LABEL_SERIES(GOB_PANE(gob), "gob pane"); GOB_TAIL(gob) = count; index = 0; } else { if (change) { if (index + count > GOB_TAIL(gob)) { EXPAND_SERIES_TAIL(GOB_PANE(gob), index + count - GOB_TAIL(gob)); } } else { Expand_Series(GOB_PANE(gob), index, count); if (index >= GOB_TAIL(gob)) index = GOB_TAIL(gob)-1; } } ptr = GOB_SKIP(gob, index); for (n = 0; n < len; n++) { val = arg++; if (IS_WORD(val)) val = Get_Var(val); if (IS_GOB(val)) { if GOB_PARENT(VAL_GOB(val)) Trap_Temp(); *ptr++ = VAL_GOB(val); GOB_PARENT(VAL_GOB(val)) = gob; SET_GOB_STATE(VAL_GOB(val), GOBS_NEW); } } }
*/ static void process_gobs(REBCMP_CTX* ctx, REBGOB* gob) /* ** Recursively process and compose gob and its children. ** ** NOTE: this function is used internally by rebcmp_compose() call only. ** ***********************************************************************/ { //RL_Print("process_gobs: %x\n", gob); REBINT x = ROUND_TO_INT(ctx->absOffset.x); REBINT y = ROUND_TO_INT(ctx->absOffset.y); REBYTE* color; Region saved_win_region = XCreateRegion(); if (GET_GOB_STATE(gob, GOBS_NEW)){ //reset old-offset and old-size if newly added GOB_XO(gob) = GOB_LOG_X(gob); GOB_YO(gob) = GOB_LOG_Y(gob); GOB_WO(gob) = GOB_LOG_W(gob); GOB_HO(gob) = GOB_LOG_H(gob); CLR_GOB_STATE(gob, GOBS_NEW); } //intersect gob dimensions with actual window clip region REBOOL valid_intersection = 1; //------------------------------ //Put backend specific code here //------------------------------ XRectangle rect; rect.x = x; rect.y = y; rect.width = GOB_LOG_W(gob); rect.height = GOB_LOG_H(gob); /* RL_Print("gob , left: %d,\ttop: %d,\tright: %d,\tbottom: %d\n", rect.x, rect.y, rect.x + rect.width, rect.y + rect.height); */ Region reg = XCreateRegion(); XUnionRectWithRegion(&rect, reg, reg); /* XClipBox(ctx->Win_Region, &rect); RL_Print("Win Region , left: %d,\ttop: %d,\tright: %d,\tbottom: %d\n", rect.x, rect.y, rect.x + rect.width, rect.y + rect.height); */ XUnionRegion(saved_win_region, ctx->Win_Region, saved_win_region); XIntersectRegion(reg, ctx->Win_Region, ctx->Win_Region); XClipBox(ctx->Win_Region, &rect); /* RL_Print("Win and Gob, left: %d,\ttop: %d,\tright: %d,\tbottom: %d\n", rect.x, rect.y, rect.x + rect.width, rect.y + rect.height); */ //get the current Window clip box REBRECT gob_clip = { rect.x, //left rect.y, //top rect.width + rect.x, //right rect.height + rect.y //bottom /* GOB_LOG_X(gob), //left GOB_LOG_Y(gob), //top GOB_LOG_W(gob) + GOB_LOG_X(gob), //right GOB_LOG_H(gob) + GOB_LOG_Y(gob), //bottom */ }; //RL_Print("Window_Buffer: 0x%x\n", ctx->Window_Buffer); /* RL_Print("gob clip , left: %d,\ttop: %d,\tright: %d,\tbottom: %d\n", gob_clip.left, gob_clip.top, gob_clip.right, gob_clip.bottom); */ if (!XEmptyRegion(ctx->Win_Region)) //if (valid_intersection) { //render GOB content switch (GOB_TYPE(gob)) { case GOBT_COLOR: //------------------------------ //Put backend specific code here //------------------------------ // or use the similar draw api call: //RL_Print("Draw Color at: %d, %d\n", x, y); rebdrw_gob_color(gob, ctx->Window_Buffer, ctx->winBufSize, (REBXYI){x,y}, (REBXYI){gob_clip.left, gob_clip.top}, (REBXYI){gob_clip.right, gob_clip.bottom}); break; case GOBT_IMAGE: { //RL_Print("Draw Image\n"); //------------------------------ //Put backend specific code here //------------------------------ // or use the similar draw api call: rebdrw_gob_image(gob, ctx->Window_Buffer, ctx->winBufSize, (REBXYI){x,y}, (REBXYI){gob_clip.left, gob_clip.top}, (REBXYI){gob_clip.right, gob_clip.bottom}); } break; case GOBT_DRAW: { //RL_Print("Draw Draw at: %d, %d\n", x, y); //------------------------------ //Put backend specific code here //------------------------------ // or use the similar draw api call: rebdrw_gob_draw(gob, ctx->Window_Buffer ,ctx->winBufSize, (REBXYI){x,y}, (REBXYI){gob_clip.left, gob_clip.top}, (REBXYI){gob_clip.right, gob_clip.bottom}); } break; case GOBT_TEXT: case GOBT_STRING: //RL_Print("Draw Text at: %d, %d\n", x, y); //------------------------------ //Put backend specific code here //------------------------------ // or use the similar draw api call: rt_gob_text(gob, ctx->Window_Buffer ,ctx->winBufSize,ctx->absOffset, (REBXYI){gob_clip.left, gob_clip.top}, (REBXYI){gob_clip.right, gob_clip.bottom}); break; case GOBT_EFFECT: //RL_Print("Draw Effect\n"); //not yet implemented break; } //recursively process sub GOBs if (GOB_PANE(gob)) { REBINT n; REBINT len = GOB_TAIL(gob); REBGOB **gp = GOB_HEAD(gob); for (n = 0; n < len; n++, gp++) { REBINT g_x = GOB_LOG_X(*gp); REBINT g_y = GOB_LOG_Y(*gp); //restore the "parent gob" clip region //------------------------------ //Put backend specific code here //------------------------------ ctx->absOffset.x += g_x; ctx->absOffset.y += g_y; process_gobs(ctx, *gp); ctx->absOffset.x -= g_x; ctx->absOffset.y -= g_y; } } } XDestroyRegion(reg); XDestroyRegion(ctx->Win_Region); ctx->Win_Region = saved_win_region; }
*/ static REBFLG Get_GOB_Var(REBGOB *gob, REBVAL *word, REBVAL *val) /* ***********************************************************************/ { REBSER *data; switch (VAL_WORD_CANON(word)) { case SYM_OFFSET: SET_PAIR(val, GOB_X(gob), GOB_Y(gob)); break; case SYM_SIZE: SET_PAIR(val, GOB_W(gob), GOB_H(gob)); break; case SYM_IMAGE: if (GOB_TYPE(gob) == GOBT_IMAGE) { // image } else goto is_none; break; #ifdef HAS_WIDGET_GOB case SYM_WIDGET: data = VAL_SERIES(GOB_WIDGET_SPEC(gob)); Init_Word(val, VAL_WORD_CANON(BLK_HEAD(data))); VAL_SET(val, REB_LIT_WORD); break; #endif case SYM_DRAW: if (GOB_TYPE(gob) == GOBT_DRAW) { Set_Block(val, GOB_CONTENT(gob)); // Note: compiler optimizes SET_BLOCKs below } else goto is_none; break; case SYM_TEXT: if (GOB_TYPE(gob) == GOBT_TEXT) { Set_Block(val, GOB_CONTENT(gob)); } else if (GOB_TYPE(gob) == GOBT_STRING) { Set_String(val, GOB_CONTENT(gob)); } else goto is_none; break; case SYM_EFFECT: if (GOB_TYPE(gob) == GOBT_EFFECT) { Set_Block(val, GOB_CONTENT(gob)); } else goto is_none; break; case SYM_COLOR: if (GOB_TYPE(gob) == GOBT_COLOR) { Set_Tuple_Pixel((REBYTE*)&GOB_CONTENT(gob), val); } else goto is_none; break; case SYM_ALPHA: SET_INTEGER(val, GOB_ALPHA(gob)); break; case SYM_PANE: if (GOB_PANE(gob)) Set_Block(val, Pane_To_Block(gob, 0, -1)); else Set_Block(val, Make_Block(0)); break; case SYM_PARENT: if (GOB_PARENT(gob)) { SET_GOB(val, GOB_PARENT(gob)); } else is_none: SET_NONE(val); break; case SYM_DATA: #ifdef HAS_WIDGET_GOB if (GOB_TYPE(gob) == GOBT_WIDGET) { return OS_GET_WIDGET_DATA(gob, val); } #endif data = GOB_DATA(gob); if (GOB_DTYPE(gob) == GOBD_OBJECT) { SET_OBJECT(val, data); } else if (GOB_DTYPE(gob) == GOBD_BLOCK) { Set_Block(val, data); } else if (GOB_DTYPE(gob) == GOBD_STRING) { Set_String(val, data); } else if (GOB_DTYPE(gob) == GOBD_BINARY) { SET_BINARY(val, data); } else if (GOB_DTYPE(gob) == GOBD_INTEGER) { SET_INTEGER(val, (REBIPT)data); } else goto is_none; break; case SYM_FLAGS: Set_Block(val, Flags_To_Block(gob)); break; default: return FALSE; } return TRUE; }
*/ static REBFLG Set_GOB_Var(REBGOB *gob, REBVAL *word, REBVAL *val) /* ***********************************************************************/ { REBVAL *spec; REBVAL *hndl; switch (VAL_WORD_CANON(word)) { case SYM_OFFSET: return Set_Pair(&(gob->offset), val); case SYM_SIZE: return Set_Pair(&gob->size, val); case SYM_IMAGE: CLR_GOB_OPAQUE(gob); if (IS_IMAGE(val)) { SET_GOB_TYPE(gob, GOBT_IMAGE); GOB_W(gob) = (REBD32)VAL_IMAGE_WIDE(val); GOB_H(gob) = (REBD32)VAL_IMAGE_HIGH(val); GOB_CONTENT(gob) = VAL_SERIES(val); // if (!VAL_IMAGE_TRANSP(val)) SET_GOB_OPAQUE(gob); } else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE); else return FALSE; break; #ifdef HAS_WIDGET_GOB case SYM_WIDGET: //printf("WIDGET GOB\n"); SET_GOB_TYPE(gob, GOBT_WIDGET); SET_GOB_OPAQUE(gob); GOB_CONTENT(gob) = Make_Block(4); // [handle type spec data] hndl = Append_Value(GOB_CONTENT(gob)); Append_Value(GOB_CONTENT(gob)); // used to cache type on host's side spec = Append_Value(GOB_CONTENT(gob)); Append_Value(GOB_CONTENT(gob)); // used to cache result data SET_HANDLE(hndl, 0, SYM_WIDGET, 0); if (IS_WORD(val) || IS_LIT_WORD(val)) { Set_Block(spec, Make_Block(1)); Append_Val(VAL_SERIES(spec), val); } else if (IS_BLOCK(val)) { Set_Block(spec, VAL_SERIES(val)); } else return FALSE; break; #endif // HAS_WIDGET_GOB case SYM_DRAW: CLR_GOB_OPAQUE(gob); if (IS_BLOCK(val)) { SET_GOB_TYPE(gob, GOBT_DRAW); GOB_CONTENT(gob) = VAL_SERIES(val); } else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE); else return FALSE; break; case SYM_TEXT: CLR_GOB_OPAQUE(gob); if (IS_BLOCK(val)) { SET_GOB_TYPE(gob, GOBT_TEXT); GOB_CONTENT(gob) = VAL_SERIES(val); } else if (IS_STRING(val)) { SET_GOB_TYPE(gob, GOBT_STRING); GOB_CONTENT(gob) = VAL_SERIES(val); } else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE); else return FALSE; break; case SYM_EFFECT: CLR_GOB_OPAQUE(gob); if (IS_BLOCK(val)) { SET_GOB_TYPE(gob, GOBT_EFFECT); GOB_CONTENT(gob) = VAL_SERIES(val); } else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE); else return FALSE; break; case SYM_COLOR: CLR_GOB_OPAQUE(gob); if (IS_TUPLE(val)) { SET_GOB_TYPE(gob, GOBT_COLOR); Set_Pixel_Tuple((REBYTE*)&GOB_CONTENT(gob), val); if (VAL_TUPLE_LEN(val) < 4 || VAL_TUPLE(val)[3] == 255) SET_GOB_OPAQUE(gob); } else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE); break; case SYM_PANE: if (GOB_PANE(gob)) Clear_Series(GOB_PANE(gob)); if (IS_BLOCK(val)) Insert_Gobs(gob, VAL_BLK_DATA(val), 0, VAL_BLK_LEN(val), 0); else if (IS_GOB(val)) Insert_Gobs(gob, val, 0, 1, 0); else if (IS_NONE(val)) gob->pane = 0; else return FALSE; break; case SYM_ALPHA: GOB_ALPHA(gob) = Clip_Int(Int32(val), 0, 255); break; case SYM_DATA: #ifdef HAS_WIDGET_GOB if (GOB_TYPE(gob) == GOBT_WIDGET) { OS_SET_WIDGET_DATA(gob, val); } else { #endif SET_GOB_DTYPE(gob, GOBD_NONE); if (IS_OBJECT(val)) { SET_GOB_DTYPE(gob, GOBD_OBJECT); SET_GOB_DATA(gob, VAL_OBJ_FRAME(val)); } else if (IS_BLOCK(val)) { SET_GOB_DTYPE(gob, GOBD_BLOCK); SET_GOB_DATA(gob, VAL_SERIES(val)); } else if (IS_STRING(val)) { SET_GOB_DTYPE(gob, GOBD_STRING); SET_GOB_DATA(gob, VAL_SERIES(val)); } else if (IS_BINARY(val)) { SET_GOB_DTYPE(gob, GOBD_BINARY); SET_GOB_DATA(gob, VAL_SERIES(val)); } else if (IS_INTEGER(val)) { SET_GOB_DTYPE(gob, GOBD_INTEGER); SET_GOB_DATA(gob, (void*)(REBIPT)VAL_INT64(val)); } else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE); else return FALSE; #ifdef HAS_WIDGET_GOB } #endif break; case SYM_FLAGS: if (IS_WORD(val)) Set_Gob_Flag(gob, val); else if (IS_BLOCK(val)) { gob->flags = 0; for (val = VAL_BLK(val); NOT_END(val); val++) { if (IS_WORD(val)) Set_Gob_Flag(gob, val); } } break; case SYM_OWNER: if (IS_GOB(val)) GOB_TMP_OWNER(gob) = VAL_GOB(val); else return FALSE; break; default: return FALSE; } return TRUE; }
*/ static void process_gobs(REBCMP_CTX* ctx, REBGOB* gob) /* ** Recursively process and compose gob and its children. ** ** NOTE: this function is used internally by rebcmp_compose() call only. ** ***********************************************************************/ { REBINT x = ROUND_TO_INT(ctx->absOffset.x); REBINT y = ROUND_TO_INT(ctx->absOffset.y); if (GET_GOB_STATE(gob, GOBS_NEW)){ //reset old-offset and old-size if newly added GOB_XO(gob) = GOB_LOG_X(gob); GOB_YO(gob) = GOB_LOG_Y(gob); GOB_WO(gob) = GOB_LOG_W(gob); GOB_HO(gob) = GOB_LOG_H(gob); CLR_GOB_STATE(gob, GOBS_NEW); } //intersect gob dimensions with actual window clip region REBOOL valid_intersection; //------------------------------ //Put backend specific code here //------------------------------ //get the current Window clip box REBRECT gob_clip; //------------------------------ //Put backend specific code here //------------------------------ if (valid_intersection) { //render GOB content switch (GOB_TYPE(gob)) { case GOBT_COLOR: //------------------------------ //Put backend specific code here //------------------------------ // or use the similar draw api call: // rebdrw_gob_color(gob, ctx->Window_Buffer, ctx->winBufSize, (REBXYI){x,y}, (REBXYI){gob_clip.left, gob_clip.top}, (REBXYI){gob_clip.right, gob_clip.bottom}); break; case GOBT_IMAGE: { //------------------------------ //Put backend specific code here //------------------------------ // or use the similar draw api call: // rebdrw_gob_image(gob, ctx->Window_Buffer, ctx->winBufSize, (REBXYI){x,y}, (REBXYI){gob_clip.left, gob_clip.top}, (REBXYI){gob_clip.right, gob_clip.bottom}); } break; case GOBT_DRAW: { //------------------------------ //Put backend specific code here //------------------------------ // or use the similar draw api call: // rebdrw_gob_draw(gob, ctx->Window_Buffer ,ctx->winBufSize, (REBXYI){x,y}, (REBXYI){gob_clip.left, gob_clip.top}, (REBXYI){gob_clip.right, gob_clip.bottom}); } break; case GOBT_TEXT: case GOBT_STRING: //------------------------------ //Put backend specific code here //------------------------------ // or use the similar draw api call: // rt_gob_text(gob, ctx->Window_Buffer ,ctx->winBufSize,ctx->absOffset, (REBXYI){gob_clip.left, gob_clip.top}, (REBXYI){gob_clip.right, gob_clip.bottom}); break; case GOBT_EFFECT: //not yet implemented break; } //recursively process sub GOBs if (GOB_PANE(gob)) { REBINT n; REBINT len = GOB_TAIL(gob); REBGOB **gp = GOB_HEAD(gob); for (n = 0; n < len; n++, gp++) { REBINT g_x = GOB_LOG_X(*gp); REBINT g_y = GOB_LOG_Y(*gp); //restore the "parent gob" clip region //------------------------------ //Put backend specific code here //------------------------------ ctx->absOffset.x += g_x; ctx->absOffset.y += g_y; process_gobs(ctx, *gp); ctx->absOffset.x -= g_x; ctx->absOffset.y -= g_y; } } } }