*/ 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 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; }
*/ 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; } } } }