bool readOffsetTable(FILE* fontFile, OffsetTable* in_pOffsetTable) { if (fread(in_pOffsetTable, sizeof(OffsetTable), 1, fontFile)!=1) return false; MTAx::Endianess::switchEndianess(&in_pOffsetTable->numTables); MTAx::Endianess::switchEndianess(&in_pOffsetTable->searchRange); MTAx::Endianess::switchEndianess(&in_pOffsetTable->entrySelector); MTAx::Endianess::switchEndianess(&in_pOffsetTable->rangeShift); if (memcmp(&in_pOffsetTable->sfntVersion, csfntVersion, 4)) return false; if (in_pOffsetTable->searchRange != 16*1<<floorLog2(in_pOffsetTable->numTables)) return false; if (in_pOffsetTable->entrySelector != floorLog2(in_pOffsetTable->numTables)) return false; if (in_pOffsetTable->rangeShift != in_pOffsetTable->numTables*16-in_pOffsetTable->searchRange) return false; return true; }
uint_t ceilLog2(T n) { uint_t r = floorLog2(n); return n > (((T)1) << r) ? r + 1 : r; }
uint_t bitsize(T n) { return floorLog2(n) + 1; }
// Render a scene Boolean v4pRender() { List l, pl ; PolygonP p, polyVisible ; ActiveEdgeP b ; Coord y, px, px_collide ; Coord yu; int su, ou1, ou2, ru1, ru2; ILayer z ; PolygonP layers[16] ; int zMax ; UInt16 bz, bi ; // bit-word of layers & collides UInt16 mi ; // masques ICollide i, colli1, colli2 ; int nColli ; PolygonP pColli[16] ; Boolean sortNeeded ; v4pDisplaySetContext(v4p->display); v4pDisplayStart() ; // update AE lists and build an y-index hash table QuickTableReset(v4p->openableAETable); v4pBuildOpenableAELists(v4p->scene->polygons); // list of opened ActiveEdges v4p->openedAEList = NULL ; // yu (scanline y in absolute coordinates) progression during scanline loop ou1 = v4p->divyvub ; ou2 = v4p->divyvub + 1 ; yu = v4p->yvu0 - ou2; ru1 = v4p->modyvub ; ru2 = v4p->modyvub - v4pDisplayHeight ; su = v4p->modyvub; // scan-line loop for (y = 0 ; y < v4pDisplayHeight ; y++) { sortNeeded = false ; if (su >= 0) { su+= ru2 ; yu+= ou2 ; } else { su+= ru1 ; yu+= ou1 ; } // loop among opened ActiveEdge l = v4p->openedAEList ; pl = NULL ; px = -(0x7FFF) ; // not sure its really the min, but we dont care while (l) { b = (ActiveEdgeP)ListData(l); if (b->h <= 0) { // close ActiveEdge if (pl) ListSetNext(pl, l = ListFree(l)) ; else v4p->openedAEList = l = ListFree(l) ; } else { // shift ActiveEdge int x ; b->h--; if (b->o2) { if (b->s > 0) { x = b->x+= b->o2 ; b->s+= b->r2 ; } else { x = b->x+= b->o1 ; b->s+= b->r1 ; } } else x = b->x ; if (x < px) sortNeeded = true ; px = x ; pl = l ; l = ListNext(l) ; } } // opened ActiveEdge loop // sort ActiveEdge if (sortNeeded) v4p->openedAEList = v4pSortActiveEdge(v4p->openedAEList) ; // open newly intersected ActiveEdge List newlyOpenedAEList = v4pOpenActiveEdge(y, yu) ; if (newlyOpenedAEList) { ListSetDataPrior(compareActiveEdgeX) ; v4p->openedAEList = ( v4p->openedAEList ? ListMerge(v4p->openedAEList, newlyOpenedAEList) : newlyOpenedAEList ) ; } // reset layers bz = 0 ; polyVisible = &(v4p->dummyBgPoly) ; zMax = -1 ; // reset collides bi = 0 ; nColli = 0 ; // loop among scanline slices px = px_collide = 0 ; for (l = v4p->openedAEList ; l ; l = ListNext(l)) { // loop ActiveEdge ouvert / x // pb = b ; b = (ActiveEdgeP)ListData(l) ; p = b->p ; z = p->z & 15 ; bz ^= ((UInt16)1 << z) ; //if (b->x > 1000) v4pDisplayDebug("problem %d %d %d", (int)b->x, (int)px, (pb ? pb->x : -1)); //if (px > b->x) v4pDisplayError("pb slice %d %d %d", (int)y, (int)px, (int)b->x); if ((int)z >= zMax) { if (px < v4pDisplayWidth && b->x > 0) v4pDisplaySlice(y, imax(px, 0), imin(b->x, v4pDisplayWidth), polyVisible->color); px = b->x ; if ((int)z > zMax) { polyVisible = layers[z] = p ; zMax = z ; } else { // z == zMax zMax = floorLog2(bz); polyVisible = (zMax >= 0 ? layers[zMax] : &(v4p->dummyBgPoly)) ; } } else { // z < zMax layers[z] = p ; } if (nColli > 1) v4pDisplayCollide(colli1, colli2, y, px_collide, b->x, pColli[colli1], pColli[colli2]); px_collide = b->x; i = p->i ; mi = (i == (ICollide)-1 ? (UInt16)0 : (UInt16)1 << (i & 15)) ; if (layers[z]) { if (mi) { pColli[i] = p ; if (!(bi & mi)) { bi |= mi ; nColli++ ; if (nColli == 1) colli1 = i ; else if (nColli == 2) colli2 = i ; } } } else { if (bi & mi) { bi ^= mi ; nColli-- ; if (nColli == 1 && i == colli1) colli1 = colli2 ; else if (nColli == 2) { if (i == colli1) { colli1 = floorLog2(bi ^ (1 << colli2)); } else if (i == colli2) { colli2 = floorLog2(bi ^ (1 << colli1)); } } } } } // x opened ActiveEdge loop // last slice if (px < v4pDisplayWidth) v4pDisplaySlice(y, imax(0, px), v4pDisplayWidth, polyVisible->color) ; } // y loop ; l = v4p->openedAEList ; while (l) l = ListFree(l) ; v4p->openedAEList = NULL ; if (yu != v4p->yvu1 - v4p->divyvub) v4pDisplayError("problem %d != %d", (int)yu, (int)v4p->yvu1 - v4p->divyvub); v4p->changes = 0 ; v4pDisplayEnd() ; return success ; }