#help_index "Graphics/Sprite;Sprites" U0 SpriteElem2Code(CDoc *doc, CSprite *tmpg) { U8 buf1[STR_LEN], buf2[STR_LEN]; I32 *ptr; I64 i, j, k, col, width_internal; CD3I32 *p; CMeshTri *tri; if (!doc) doc = DocPut; DocPrint(doc, "%Z", tmpg->type & SPG_TYPE_MASK, "ST_SPRITE_ELEM_CODES"); switch (tmpg->type & SPG_TYPE_MASK) { case SPT_COLOR: DocPrint(doc, "{%s}", Color2Str(buf1, tmpg->c.color)); break; case SPT_DITHER_COLOR: DocPrint(doc, "{%s}", Color2Str(buf2, ROPF_DITHER | tmpg->d.dither_color.u8[0] | tmpg->d.dither_color.u8[1] << COLORROP_BITS)); break; case SPT_TRANSFORM_ON: DocPrint(doc, "{ON}"); break; case SPT_TRANSFORM_OFF: DocPrint(doc, "{OFF}"); break; case SPT_LINE: case SPT_ARROW: case SPT_PLANAR_SYMMETRY: DocPrint(doc, "{(%d,%d),(%d,%d)}", tmpg->pp.x1, tmpg->pp.y1, tmpg->pp.x2, tmpg->pp.y2); break; case SPT_RECT: DocPrint(doc, "{(%d,%d):(%d,%d)}", tmpg->pp.x1, tmpg->pp.y1, tmpg->pp.x2 - tmpg->pp.x1, tmpg->pp.y2 - tmpg->pp.y1); break; case SPT_ROTATED_RECT: DocPrint(doc, "{(%d,%d):(%d,%d),%0.4f}", tmpg->ppa.x1, tmpg->ppa.y1, tmpg->ppa.x2 - tmpg->ppa.x1, tmpg->ppa.y2 - tmpg->ppa.y1, 180 / pi * Wrap(tmpg->ppa.angle)); break; case SPT_PT: case SPT_FLOOD_FILL: case SPT_SHIFT: DocPrint(doc, "{(%d,%d)}", tmpg->p.x1, tmpg->p.y1); break; case SPT_FLOOD_FILL_NOT: DocPrint(doc, "{(%d,%d),TRUE}", tmpg->p.x1, tmpg->p.y1); break; case SPT_CIRCLE: DocPrint(doc, "{(%d,%d):%d}", tmpg->pr.x1, tmpg->pr.y1, tmpg->pr.radius); break; case SPT_THICK: DocPrint(doc, "{%d}", tmpg->t.thick); break; case SPT_ELLIPSE: DocPrint(doc, "{(%d,%d):(%d,%d),%0.4f}", tmpg->pwha.x1, tmpg->pwha.y1, tmpg->pwha.width, tmpg->pwha.height, 180 / pi * Wrap(tmpg->pwha.angle)); break; case SPT_POLYGON: DocPrint(doc, "{%d,(%d,%d):(%d,%d),%0.4f}", tmpg->pwhas.sides, tmpg->pwhas.x1, tmpg->pwhas.y1, tmpg->pwhas.width, tmpg->pwhas.height, 180 / pi * Wrap(tmpg->pwhas.angle)); break; case SPT_TEXT: case SPT_TEXT_BOX: case SPT_TEXT_DIAMOND: DocPrint(doc, "{(%d,%d),\"%Q\"}", tmpg->ps.x1, tmpg->ps.y1, tmpg->ps.st); break; case SPT_POLYLINE: ptr = &tmpg->nu.u; DocPrint(doc, "{"); for (i = 0; i < tmpg->nu.num; i++, ptr += 2) { DocPrint(doc, "(%d,%d)", ptr[0], ptr[1]); if (i + 1 < tmpg->nu.num) DocPrint(doc, ","); if (i & 3 == 3 && i + 1 < tmpg->nu.num) DocPrint(doc, "\n"); } DocPrint(doc, "}"); break; case SPT_BSPLINE2: case SPT_BSPLINE3: case SPT_BSPLINE2_CLOSED: case SPT_BSPLINE3_CLOSED: ptr = &tmpg->nu.u; DocPrint(doc, "{"); for (i = 0; i < tmpg->nu.num; i++, ptr += 3) { DocPrint(doc, "(%d,%d,%d)", ptr[0], ptr[1], ptr[2]); if (i + 1 < tmpg->nu.num) DocPrint(doc, ","); if (i & 3 == 3 && i + 1 < tmpg->nu.num) DocPrint(doc, "\n"); } if (tmpg->type & SPG_TYPE_MASK == SPT_BSPLINE2 || tmpg->type & SPG_TYPE_MASK == SPT_BSPLINE3) DocPrint(doc, ",FALSE}"); else DocPrint(doc, ",TRUE}"); break; case SPT_POLYPT: DocPrint(doc, "{(%d,%d),", tmpg->npu.x, tmpg->npu.y); ptr = &tmpg->npu.u; col = 16; for (i= 0 ; i < tmpg->npu.num; i++) { DocPrint(doc, "%d", BFieldExtU32(ptr, i * 3, 3)); if (++col >= 64 && i + 1 < tmpg->npu.num) { DocPrint(doc, "\n"); col = 0; } } DocPrint(doc, "}"); break; case SPT_BITMAP: DocPrint(doc, "{(%d,%d):(%d,%d),\n", tmpg->pwhu.x1, tmpg->pwhu.y1, tmpg->pwhu.width, tmpg->pwhu.height); width_internal = (tmpg->pwhu.width + 7) & ~7; if (width_internal < 80) k = width_internal; else k = 64; ptr = &tmpg->pwhu.u; col = 0; for (j = 0; j < tmpg->pwhu.height; j++) for (i = 0; i < width_internal; i++, ptr(U8 *)++) { if (i >= tmpg->pwhu.width) DocPrint(doc, "_"); else if (*ptr(U8 *) < 16) DocPrint(doc, "%X", *ptr(U8 *)); else DocPrint(doc, " "); if (++col >= k && (i + 1 < width_internal || j + 1 < tmpg->pwhu.height)) { DocPrint(doc, "\n"); col = 0; } } DocPrint(doc, "}"); break; case SPT_MESH: DocPrint(doc, "{FALSE,"); p = &tmpg->mu.u; col = 0; for (i = 0; i < tmpg->mu.vertex_count; i++, p++) { DocPrint(doc, "(%d,%d,%d)", p->x, p->y, p->z); if (i + 1 < tmpg->mu.vertex_count) DocPrint(doc, ","); if (++col == 4) { DocPrint(doc, "\t//%d\n", i); col = 0; } } DocPrint(doc, ":"); tri = p; for (i = 0; i < tmpg->mu.tri_count; i++, tri++) { DocPrint(doc, "(%s,%d,%d,%d)", Color2Str(buf1, tri->color), tri->nums[0], tri->nums[1], tri->nums[2]); if (i + 1 < tmpg->mu.tri_count) DocPrint(doc, ","); if (++col >= 3 && i + 1 < tmpg->mu.tri_count) { DocPrint(doc, "\n"); col = 0; } } DocPrint(doc, "}"); break; case SPT_SHIFTABLE_MESH: DocPrint(doc, "{TRUE,(%d,%d,%d):", tmpg->pmu.x, tmpg->pmu.y, tmpg->pmu.z); p = &tmpg->pmu.u; col = 1; for (i = 0; i < tmpg->pmu.vertex_count; i++, p++) { DocPrint(doc, "(%d,%d,%d)", p->x, p->y, p->z); if (i + 1 < tmpg->pmu.vertex_count) DocPrint(doc, ","); if (++col == 4) { DocPrint(doc, "\t//%d\n", i); col = 0; } } DocPrint(doc, ":"); tri = p; for (i = 0; i < tmpg->pmu.tri_count; i++, tri++) { DocPrint(doc, "(%s,%d,%d,%d)", Color2Str(buf1, tri->color), tri->nums[0], tri->nums[1], tri->nums[2]); if (i + 1 < tmpg->pmu.tri_count) DocPrint(doc, ","); if (++col >= 3 && i + 1 < tmpg->pmu.tri_count) { DocPrint(doc, "\n"); col = 0; } } DocPrint(doc, "}"); break; } DocPrint(doc, ";\n"); } public U0 Sprite2Code(CDoc *doc=NULL, U8 *elems) {//Sprite to text. CSprite *tmpg = elems - offset(CSprite.start); while (tmpg->type & SPG_TYPE_MASK) { SpriteElem2Code(doc, tmpg); tmpg(U8 *) += SpriteElemSize(tmpg); } } CSprite *Code2SpriteElem(CCompCtrl *cc, I64 type) { I64 i, num1, num2, size; CSprite *res, g; CColorROPU32 color; U8 *st, *ptr; CQueueD3I32 headp, *tmpp, *tmpa1; CQueueMeshTri headt, *tmpt, *tmpt1; CQueueVectU8 *tmpv; MemSet(&g, 0, sizeof(CSprite)); switch (type) { start: case SPT_COLOR: case SPT_DITHER_COLOR: st = LexFirstRemove(cc, "}"); color = Str2ColorU32(st); Free(st); Lex(cc); //Skip color g.c.color = color.c0.color; if (color & ROPF_DITHER) { g.d.dither_color.u8[1] = color.c1.color; g.type = SPT_DITHER_COLOR; } else g.type = SPT_COLOR; break; case SPT_TRANSFORM_ON: case SPT_TRANSFORM_OFF: Lex(cc); //Skip { if (LexExpressionI64(cc)) g.type = SPT_TRANSFORM_ON; else g.type = SPT_TRANSFORM_OFF; break; case SPT_LINE: case SPT_ARROW: case SPT_PLANAR_SYMMETRY: Lex(cc); //Skip { g.type = type; LexD2I32(cc, &g.pp.x1); if (cc->token != ',') LexExcept(cc, "Expecting ',' at "); Lex(cc); //Skip , LexD2I32(cc, &g.pp.x2); break; case SPT_RECT: case SPT_ROTATED_RECT: Lex(cc); //Skip { LexD2I32(cc, &g.pp.x1); if (cc->token != ':') LexExcept(cc, "Expecting ':' at "); Lex(cc); //Skip : LexD2I32(cc, &g.pp.x2); g.ppa.x2 += g.pp.x1; g.ppa.y2 += g.pp.y1; if (cc->token == ',') { Lex(cc); //Skip , g.ppa.angle = pi / 180 * LexExpressionF64(cc); g.type = SPT_ROTATED_RECT; } else g.type = SPT_RECT; break; case SPT_PT: case SPT_SHIFT: Lex(cc); //Skip { g.type = type; LexD2I32(cc, &g.p.x1); break; case SPT_FLOOD_FILL: case SPT_FLOOD_FILL_NOT: Lex(cc); //Skip { LexD2I32(cc, &g.p.x1); if (cc->token == ',') { Lex(cc); //Skip , i = LexExpressionI64(cc); } else i = 0; if (i) g.type = SPT_FLOOD_FILL_NOT; else g.type = SPT_FLOOD_FILL; break; case SPT_THICK: Lex(cc); //Skip { g.t.thick = LexExpressionI64(cc); g.type = SPT_THICK; break; case SPT_CIRCLE: Lex(cc); //Skip { g.type = SPT_CIRCLE; LexD2I32(cc, &g.pr.x1); if (cc->token != ':') LexExcept(cc, "Expecting ':' at "); Lex(cc); //Skip : g.pr.radius = LexExpressionI64(cc); break; case SPT_POLYGON: Lex(cc); //Skip { g.pwhas.sides = LexExpressionI64(cc); if (cc->token != ',') LexExcept(cc, "Expecting ',' at "); case SPT_ELLIPSE: Lex(cc); //Skip { g.type = type; LexD2I32(cc, &g.pwha.x1); if (cc->token != ':') LexExcept(cc, "Expecting ':' at "); Lex(cc); //Skip : LexD2I32(cc, &g.pwha.width); if (cc->token != ',') LexExcept(cc, "Expecting ',' at "); Lex(cc); //Skip , g.pwha.angle = pi / 180 * LexExpressionF64(cc); break; end: size = SpriteElemSize(&g) + offset(CSprite.start); res = MAlloc(size); MemCopy(res, &g, size); break; case SPT_TEXT: case SPT_TEXT_BOX: case SPT_TEXT_DIAMOND: Lex(cc); //Skip { g.type = type; LexD2I32(cc, &g.ps.x1); if (cc->token != ',') LexExcept(cc, "Expecting ',' at "); if (Lex(cc) == TK_STR) //Skip , st = LexExtStr(cc); else LexExcept(cc, "Expecting string at "); size = SpriteElemQueuedBaseSize(type); i = StrLen(st) + 1; res = MAlloc(size + i); MemCopy(res, &g, size); MemCopy(res(U8 *) + size, st, i); Free(st); break; case SPT_POLYLINE: Lex(cc); //Skip { g.type = SPT_POLYLINE; QueueInit(&headp); while (cc->token == '(') { tmpp = CAlloc(sizeof(CQueueD3I32)); LexD2I32(cc, &tmpp->p); QueueInsert(tmpp, headp.last); g.nu.num++; if (cc->token == ',') Lex(cc); //Skip , } if (g.nu.num < 2) LexExcept(cc, "Expecting point at "); size = SpriteElemQueuedBaseSize(SPT_POLYLINE); res = MAlloc(size + g.nu.num * sizeof(CD2I32)); MemCopy(res, &g, size); ptr = &res->nu.u; tmpp = headp.next; while (tmpp != &headp) { tmpa1 = tmpp->next; MemCopy(ptr, &tmpp->p, sizeof(CD2I32)); ptr += sizeof(CD2I32); Free(tmpp); tmpp = tmpa1; } break; case SPT_BSPLINE2: case SPT_BSPLINE3: case SPT_BSPLINE2_CLOSED: case SPT_BSPLINE3_CLOSED: Lex(cc); //Skip { QueueInit(&headp); while (cc->token == '(') { tmpp = CAlloc(sizeof(CQueueD3I32)); LexD3I32(cc, &tmpp->p); QueueInsert(tmpp, headp.last); g.nu.num++; if (cc->token == ',') Lex(cc); //Skip , } if (g.nu.num < 2) LexExcept(cc, "Expecting point at "); size = SpriteElemQueuedBaseSize(type); res = MAlloc(size + g.nu.num * sizeof(CD3I32)); if (LexExpressionI64(cc)) { if (type == SPT_BSPLINE2 || type == SPT_BSPLINE2_CLOSED) g.type = SPT_BSPLINE2_CLOSED; else g.type = SPT_BSPLINE3_CLOSED; } else { if (type == SPT_BSPLINE2 || type == SPT_BSPLINE2_CLOSED) g.type = SPT_BSPLINE2; else g.type = SPT_BSPLINE3; } MemCopy(res, &g, size); ptr = &res->nu.u; tmpp = headp.next; while (tmpp != &headp) { tmpa1 = tmpp->next; MemCopy(ptr, &tmpp->p, sizeof(CD3I32)); ptr += sizeof(CD3I32); Free(tmpp); tmpp = tmpa1; } break; case SPT_POLYPT: Lex(cc); //Skip { LexD2I32(cc, &g.npu.x); if (cc->token != ',') LexExcept(cc, "Expecting ',' at "); tmpv = QueueVectU8New; while (TRUE) { if (!(i = LexCharGet(cc))) LexExcept(cc, "Expecting '}' at "); if (i == '}') break; if ('0' <= i <= '7') QueueVectU8Put(tmpv, g.npu.num++, i - '0'); } Bts(&cc->flags, CCf_USE_LAST_U16); Lex(cc); //Load '}' g.type = SPT_POLYPT; size = SpriteElemQueuedBaseSize(SPT_POLYPT); res = CAlloc(size+(g.npu.num * 3 + 7 ) >> 3); MemCopy(res, &g, size); ptr = &res->npu.u; for (i = 0; i < g.npu.num; i++) BFieldOrU32(ptr, i * 3, QueueVectU8Get(tmpv, i)); QueueVectU8Del(tmpv); break; case SPT_BITMAP: Lex(cc); //Skip { LexD2I32(cc, &g.pwhu.x1); if (cc->token != ':') LexExcept(cc, "Expecting ':' at "); Lex(cc); //Skip : LexD2I32(cc, &g.pwhu.width); if (cc->token != ',') LexExcept(cc, "Expecting ',' at "); tmpv = QueueVectU8New; num1 = 0; while (TRUE) { if (!(i = ToUpper(LexCharGet(cc)))) LexExcept(cc, "Expecting '}' at "); if (i == '}') break; if ('0' <= i <= '9') QueueVectU8Put(tmpv, num1++, i - '0'); else if ('A' <= i <= 'F') QueueVectU8Put(tmpv, num1++, i - 'A' + 10); else if (i == CH_SPACE) QueueVectU8Put(tmpv, num1++, TRANSPARENT); else if (i == '_') QueueVectU8Put(tmpv, num1++, 0); } Bts(&cc->flags, CCf_USE_LAST_U16); Lex(cc); //Load '}' g.type = SPT_BITMAP; size = SpriteElemQueuedBaseSize(SPT_BITMAP); res = CAlloc(size + num1); MemCopy(res, &g, size); ptr = &res->pwhu.u; for (i = 0; i < num1; i++) *ptr++ = QueueVectU8Get(tmpv, i); QueueVectU8Del(tmpv); break; case SPT_MESH: case SPT_SHIFTABLE_MESH: Lex(cc); //Skip { if (LexExpressionI64(cc)) { g.type = SPT_SHIFTABLE_MESH; if (cc->token != ',') LexExcept(cc, "Expecting ',' at "); Lex(cc); //Skip , LexD3I32(cc, &g.pmu.x); if (cc->token != ':') LexExcept(cc, "Expecting ':' at "); Lex(cc); //Skip : } else { g.type = SPT_MESH; if (cc->token != ',') LexExcept(cc, "Expecting ',' at "); Lex(cc); //Skip , } num1 = 0; QueueInit(&headp); while (cc->token == '(') { tmpp = CAlloc(sizeof(CQueueD3I32)); LexD3I32(cc, &tmpp->p); QueueInsert(tmpp, headp.last); num1++; if (cc->token == ',') Lex(cc); //Skip , } if (cc->token != ':') LexExcept(cc, "Expecting ':' at "); Lex(cc); //Skip : num2 = 0; QueueInit(&headt); while (cc->token == '(') { tmpt = CAlloc(sizeof(CQueueMeshTri)); st = LexFirstRemove(cc, ","); tmpt->color = Str2ColorU32(st); Free(st); Lex(cc); //Skip color if (cc->token != ',') LexExcept(cc, "Expecting ',' at "); Lex(cc); //Skip , tmpt->nums[0] = LexExpressionI64(cc); if (cc->token != ',') LexExcept(cc, "Expecting ',' at "); Lex(cc); //Skip , tmpt->nums[1] = LexExpressionI64(cc); if (cc->token != ',') LexExcept(cc, "Expecting ',' at "); Lex(cc); //Skip , tmpt->nums[2] = LexExpressionI64(cc); if (cc->token != ')') LexExcept(cc, "Expecting ')' at "); Lex(cc); //Skip ) QueueInsert(tmpt, headt.last); num2++; if (cc->token == ',') Lex(cc); //Skip , } if (g.type == SPT_MESH) { g.mu.vertex_count = num1; g.mu.tri_count = num2; size = SpriteElemQueuedBaseSize(SPT_MESH); } else { g.pmu.vertex_count = num1; g.pmu.tri_count = num2; } size = SpriteElemQueuedBaseSize(g.type); res = MAlloc(size + num1 * sizeof(CD3I32) + num2 * sizeof(CMeshTri)); MemCopy(res, &g, size); ptr = res(U8 *) + size; tmpp = headp.next; while (tmpp != &headp) { tmpa1 = tmpp->next; MemCopy(ptr, &tmpp->p, sizeof(CD3I32)); ptr += sizeof(CD3I32); Free(tmpp); tmpp = tmpa1; } tmpt = headt.next; while (tmpt != &headt) { tmpt1 = tmpt->next; MemCopy(ptr, &tmpt->start, sizeof(CMeshTri)); ptr += sizeof(CMeshTri); Free(tmpt); tmpt = tmpt1; } break; } if (cc->token != '}') LexExcept(cc, "Expecting '}' at "); if (Lex(cc) != ';') LexExcept(cc, "Expecting ';' at "); return res; } public U8 *Code2Sprite(CDoc *doc, I64 *_size=NULL) {//Text to sprite. CSprite head; U8 *res; Bool okay = TRUE, unlock_doc = DocLock(doc); CCompCtrl *cc = CompCtrlNew(, CCF_DONT_FREE_BUF); CHashTable *old_hash_table_list = cc->htc.hash_table_list; CHashGeneric *tmph; I64 i, size = 0; QueueInit(&head); LexAttachDoc(cc,, doc); try { do { cc->htc.hash_table_list = NULL; if (Lex(cc) == TK_IDENT /*Skip ; */ && (tmph = HashFind(cc->cur_str, gr.sprite_hash, SPHT_ELEM_CODE))) { i = tmph->user_data0; cc->htc.hash_table_list = old_hash_table_list; if (Lex(cc) == '{') //Skip ident QueueInsert(Code2SpriteElem(cc, i), head.last); } else if (cc->token) LexExcept(cc, "Expecting sprite element type name at "); } while (cc->token); okay = TRUE; } catch { Fs->catch_except = TRUE; okay = FALSE; } if (unlock_doc) DocUnlock(doc); if (okay) { CompCtrlDel(cc); //TODO: can crash res = SpriteQueue2Sprite(&head, &size); } else { res = NULL; size = 0; } if (_size) *_size = size; QueueDel(&head); return res; }