*/ static REBSER *Pane_To_Block(REBGOB *gob, REBCNT index, REBINT len) /* ** Convert pane list of gob pointers to a block of GOB!s. ** ***********************************************************************/ { REBSER *ser; REBGOB **gp; REBVAL *val; if (len == -1 || (len + index) > GOB_TAIL(gob)) len = GOB_TAIL(gob) - index; if (len < 0) len = 0; ser = Make_Block(len); ser->tail = len; val = BLK_HEAD(ser); gp = GOB_HEAD(gob); for (; len > 0; len--, val++, gp++) { SET_GOB(val, *gp); } SET_END(val); return ser; }
*/ 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; }
*/ 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 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 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; } } } }