EStatusCode CFFEmbeddedFontWriter::WriteCharStrings(const UIntVector& inSubsetGlyphIDs) { /* 1. build the charstrings data, looping the glyphs charstrings and writing a flattened version of each charstring 2. write the charstring index based on offsets inside the data (size should be according to the max) 3. copy the data into the stream */ unsigned long* offsets = new unsigned long[inSubsetGlyphIDs.size() + 1]; MyStringBuf charStringsData; OutputStringBufferStream charStringsDataWriteStream(&charStringsData); CharStringType2Flattener charStringFlattener; UIntVector::const_iterator itGlyphs = inSubsetGlyphIDs.begin(); EStatusCode status = PDFHummus::eSuccess; do { unsigned short i=0; for(; itGlyphs != inSubsetGlyphIDs.end() && PDFHummus::eSuccess == status; ++itGlyphs,++i) { offsets[i] = (unsigned long)charStringsDataWriteStream.GetCurrentPosition(); status = charStringFlattener.WriteFlattenedGlyphProgram( 0, *itGlyphs, &(mOpenTypeInput.mCFF), &charStringsDataWriteStream); } if(status != PDFHummus::eSuccess) break; offsets[i] = (unsigned long)charStringsDataWriteStream.GetCurrentPosition(); charStringsData.pubseekoff(0,std::ios_base::beg); // write index section mCharStringPosition = mFontFileStream.GetCurrentPosition(); Byte sizeOfOffset = GetMostCompressedOffsetSize(offsets[i] + 1); mPrimitivesWriter.WriteCard16((unsigned short)inSubsetGlyphIDs.size()); mPrimitivesWriter.WriteOffSize(sizeOfOffset); mPrimitivesWriter.SetOffSize(sizeOfOffset); for(i=0;i<=inSubsetGlyphIDs.size();++i) mPrimitivesWriter.WriteOffset(offsets[i] + 1); // Write data InputStringBufferStream charStringsDataReadStream(&charStringsData); OutputStreamTraits streamCopier(&mFontFileStream); status = streamCopier.CopyToOutputStream(&charStringsDataReadStream); if(status != PDFHummus::eSuccess) break; }while(false); delete[] offsets; return status; }
EStatusCode CFFEmbeddedFontWriter::WriteFDSelect(const UIntVector& inSubsetGlyphIDs,const FontDictInfoToByteMap& inNewFontDictsIndexes) { // always write format 3. cause at most cases the FD dicts count will be so low that it'd // take a bloody mircale for no repeats to occur. UIntVector::const_iterator itGlyphs = inSubsetGlyphIDs.begin(); mFDSelectPosition = mFontFileStream.GetCurrentPosition(); mPrimitivesWriter.WriteCard8(3); LongFilePositionType rangesCountPosition = mFontFileStream.GetCurrentPosition(); mPrimitivesWriter.WriteCard16(1); // temporary. will get back to this later unsigned short rangesCount = 1; Byte currentFD,newFD; unsigned short glyphIndex = 1; FontDictInfoToByteMap::const_iterator itNewIndex = inNewFontDictsIndexes.find(mOpenTypeInput.mCFF.mTopDictIndex[0].mFDSelect[*itGlyphs]); // k. seems like i probably just imagine exceptions here. i guess there must // be a proper FDSelect with FDs for all...so i'm defaulting to some 0 currentFD = (itNewIndex == inNewFontDictsIndexes.end() ? 0:itNewIndex->second); mPrimitivesWriter.WriteCard16(0); mPrimitivesWriter.WriteCard8(currentFD); ++itGlyphs; for(; itGlyphs != inSubsetGlyphIDs.end(); ++itGlyphs,++glyphIndex) { itNewIndex = inNewFontDictsIndexes.find(mOpenTypeInput.mCFF.mTopDictIndex[0].mFDSelect[*itGlyphs]); newFD = (itNewIndex == inNewFontDictsIndexes.end() ? 0:itNewIndex->second); if(newFD != currentFD) { currentFD = newFD; mPrimitivesWriter.WriteCard16(glyphIndex); mPrimitivesWriter.WriteCard8(currentFD); ++rangesCount; } } mPrimitivesWriter.WriteCard16((unsigned short)inSubsetGlyphIDs.size()); // go back to ranges count if not equal to what's already written if(rangesCount != 1) { LongFilePositionType currentPosition = mFontFileStream.GetCurrentPosition(); mFontFileStream.SetPosition(rangesCountPosition); mPrimitivesWriter.WriteCard16(rangesCount); mFontFileStream.SetPosition(currentPosition); } return mPrimitivesWriter.GetInternalState(); }
void TowerTemporal::update(float t) { static const float sShotFadeOut = 0.5f; mTimeSinceLastAction += t; float atkDur = 1.0f/mAtkSpeed; if (mTimeSinceLastAction >= atkDur) { // Get all Aliens within the tower's range Alien* alien = NULL; UIntVector ids = getTargetsInRange(); for (size_t i = 0; i < ids.size(); ++i) { unsigned int id = ids[i]; alien = AlienFactory::getSingleton().getAlien(id); if (alien && alien->getState() != Alien::DYING && alien->getState() != Alien::DEAD) alien->slow(0.5f, atkDur*0.5f); } // Reset the scale of the shot graphics mpShotGraphics->getParentSceneNode()->setScale(Ogre::Vector3::UNIT_SCALE); mpShotGraphics->setVisible(true); // Reset the time since last action mTimeSinceLastAction = 0; } // Update the shot graphics if (mTimeSinceLastAction < sShotFadeOut) { float shotPerc = mTimeSinceLastAction / sShotFadeOut; Ogre::Vector3 scale = Ogre::Vector3::UNIT_SCALE * Ogre::Math::Sqrt(mRangeSqr) * 0.5; scale = scale * Ogre::Math::Sqrt(shotPerc); mpShotGraphics->getParentSceneNode()->setScale(scale); mpShotGraphics->beginUpdate(0); for (size_t i = 0; i < mRingVertices.size(); ++i) { mpShotGraphics->position(mRingVertices[i]); mpShotGraphics->colour(0.33, 0.33, 1, 1-shotPerc); } mpShotGraphics->end(); } else { mpShotGraphics->setVisible(false); } }
// ------------------------------------------------------------------------------------------------ // Note - this is an implementation of the standard (recursive) Cm-Cl algorithm without further // optimizations (except we're using some nice LUTs). A description of the algorithm can be found // here: http://en.wikipedia.org/wiki/Catmull-Clark_subdivision_surface // // The code is mostly O(n), however parts are O(nlogn) which is therefore the algorithm's // expected total runtime complexity. The implementation is able to work in-place on the same // mesh arrays. Calling #InternSubdivide() directly is not encouraged. The code can operate // in-place unless 'smesh' and 'out' are equal (no strange overlaps or reorderings). // Previous data is replaced/deleted then. // ------------------------------------------------------------------------------------------------ void CatmullClarkSubdivider::InternSubdivide ( const aiMesh* const * smesh, size_t nmesh, aiMesh** out, unsigned int num ) { ai_assert(NULL != smesh && NULL != out); INIT_EDGE_HASH_TEMPORARIES(); // no subdivision requested or end of recursive refinement if (!num) { return; } UIntVector maptbl; SpatialSort spatial; // --------------------------------------------------------------------- // 0. Offset table to index all meshes continuously, generate a spatially // sorted representation of all vertices in all meshes. // --------------------------------------------------------------------- typedef std::pair<unsigned int,unsigned int> IntPair; std::vector<IntPair> moffsets(nmesh); unsigned int totfaces = 0, totvert = 0; for (size_t t = 0; t < nmesh; ++t) { const aiMesh* mesh = smesh[t]; spatial.Append(mesh->mVertices,mesh->mNumVertices,sizeof(aiVector3D),false); moffsets[t] = IntPair(totfaces,totvert); totfaces += mesh->mNumFaces; totvert += mesh->mNumVertices; } spatial.Finalize(); const unsigned int num_unique = spatial.GenerateMappingTable(maptbl,ComputePositionEpsilon(smesh,nmesh)); #define FLATTEN_VERTEX_IDX(mesh_idx, vert_idx) (moffsets[mesh_idx].second+vert_idx) #define FLATTEN_FACE_IDX(mesh_idx, face_idx) (moffsets[mesh_idx].first+face_idx) // --------------------------------------------------------------------- // 1. Compute the centroid point for all faces // --------------------------------------------------------------------- std::vector<Vertex> centroids(totfaces); unsigned int nfacesout = 0; for (size_t t = 0, n = 0; t < nmesh; ++t) { const aiMesh* mesh = smesh[t]; for (unsigned int i = 0; i < mesh->mNumFaces;++i,++n) { const aiFace& face = mesh->mFaces[i]; Vertex& c = centroids[n]; for (unsigned int a = 0; a < face.mNumIndices;++a) { c += Vertex(mesh,face.mIndices[a]); } c /= static_cast<float>(face.mNumIndices); nfacesout += face.mNumIndices; } } { // we want edges to go away before the recursive calls so begin a new scope EdgeMap edges; // --------------------------------------------------------------------- // 2. Set each edge point to be the average of all neighbouring // face points and original points. Every edge exists twice // if there is a neighboring face. // --------------------------------------------------------------------- for (size_t t = 0; t < nmesh; ++t) { const aiMesh* mesh = smesh[t]; for (unsigned int i = 0; i < mesh->mNumFaces;++i) { const aiFace& face = mesh->mFaces[i]; for (unsigned int p =0; p< face.mNumIndices; ++p) { const unsigned int id[] = { face.mIndices[p], face.mIndices[p==face.mNumIndices-1?0:p+1] }; const unsigned int mp[] = { maptbl[FLATTEN_VERTEX_IDX(t,id[0])], maptbl[FLATTEN_VERTEX_IDX(t,id[1])] }; Edge& e = edges[MAKE_EDGE_HASH(mp[0],mp[1])]; e.ref++; if (e.ref<=2) { if (e.ref==1) { // original points (end points) - add only once e.edge_point = e.midpoint = Vertex(mesh,id[0])+Vertex(mesh,id[1]); e.midpoint *= 0.5f; } e.edge_point += centroids[FLATTEN_FACE_IDX(t,i)]; } } } } // --------------------------------------------------------------------- // 3. Normalize edge points // --------------------------------------------------------------------- {unsigned int bad_cnt = 0; for (EdgeMap::iterator it = edges.begin(); it != edges.end(); ++it) { if ((*it).second.ref < 2) { ai_assert((*it).second.ref); ++bad_cnt; } (*it).second.edge_point *= 1.f/((*it).second.ref+2.f); } if (bad_cnt) { // Report the number of bad edges. bad edges are referenced by less than two // faces in the mesh. They occur at outer model boundaries in non-closed // shapes. char tmp[512]; ai_snprintf(tmp, 512, "Catmull-Clark Subdivider: got %u bad edges touching only one face (totally %u edges). ", bad_cnt,static_cast<unsigned int>(edges.size())); DefaultLogger::get()->debug(tmp); }} // --------------------------------------------------------------------- // 4. Compute a vertex-face adjacency table. We can't reuse the code // from VertexTriangleAdjacency because we need the table for multiple // meshes and out vertex indices need to be mapped to distinct values // first. // --------------------------------------------------------------------- UIntVector faceadjac(nfacesout), cntadjfac(maptbl.size(),0), ofsadjvec(maptbl.size()+1,0); { for (size_t t = 0; t < nmesh; ++t) { const aiMesh* const minp = smesh[t]; for (unsigned int i = 0; i < minp->mNumFaces; ++i) { const aiFace& f = minp->mFaces[i]; for (unsigned int n = 0; n < f.mNumIndices; ++n) { ++cntadjfac[maptbl[FLATTEN_VERTEX_IDX(t,f.mIndices[n])]]; } } } unsigned int cur = 0; for (size_t i = 0; i < cntadjfac.size(); ++i) { ofsadjvec[i+1] = cur; cur += cntadjfac[i]; } for (size_t t = 0; t < nmesh; ++t) { const aiMesh* const minp = smesh[t]; for (unsigned int i = 0; i < minp->mNumFaces; ++i) { const aiFace& f = minp->mFaces[i]; for (unsigned int n = 0; n < f.mNumIndices; ++n) { faceadjac[ofsadjvec[1+maptbl[FLATTEN_VERTEX_IDX(t,f.mIndices[n])]]++] = FLATTEN_FACE_IDX(t,i); } } } // check the other way round for consistency #ifdef ASSIMP_BUILD_DEBUG for (size_t t = 0; t < ofsadjvec.size()-1; ++t) { for (unsigned int m = 0; m < cntadjfac[t]; ++m) { const unsigned int fidx = faceadjac[ofsadjvec[t]+m]; ai_assert(fidx < totfaces); for (size_t n = 1; n < nmesh; ++n) { if (moffsets[n].first > fidx) { const aiMesh* msh = smesh[--n]; const aiFace& f = msh->mFaces[fidx-moffsets[n].first]; bool haveit = false; for (unsigned int i = 0; i < f.mNumIndices; ++i) { if (maptbl[FLATTEN_VERTEX_IDX(n,f.mIndices[i])]==(unsigned int)t) { haveit = true; break; } } ai_assert(haveit); if (!haveit) { DefaultLogger::get()->debug("Catmull-Clark Subdivider: Index not used"); } break; } } } } #endif } #define GET_ADJACENT_FACES_AND_CNT(vidx,fstartout,numout) \ fstartout = &faceadjac[ofsadjvec[vidx]], numout = cntadjfac[vidx] typedef std::pair<bool,Vertex> TouchedOVertex; std::vector<TouchedOVertex > new_points(num_unique,TouchedOVertex(false,Vertex())); // --------------------------------------------------------------------- // 5. Spawn a quad from each face point to the corresponding edge points // the original points being the fourth quad points. // --------------------------------------------------------------------- for (size_t t = 0; t < nmesh; ++t) { const aiMesh* const minp = smesh[t]; aiMesh* const mout = out[t] = new aiMesh(); for (unsigned int a = 0; a < minp->mNumFaces; ++a) { mout->mNumFaces += minp->mFaces[a].mNumIndices; } // We need random access to the old face buffer, so reuse is not possible. mout->mFaces = new aiFace[mout->mNumFaces]; mout->mNumVertices = mout->mNumFaces*4; mout->mVertices = new aiVector3D[mout->mNumVertices]; // quads only, keep material index mout->mPrimitiveTypes = aiPrimitiveType_POLYGON; mout->mMaterialIndex = minp->mMaterialIndex; if (minp->HasNormals()) { mout->mNormals = new aiVector3D[mout->mNumVertices]; } if (minp->HasTangentsAndBitangents()) { mout->mTangents = new aiVector3D[mout->mNumVertices]; mout->mBitangents = new aiVector3D[mout->mNumVertices]; } for(unsigned int i = 0; minp->HasTextureCoords(i); ++i) { mout->mTextureCoords[i] = new aiVector3D[mout->mNumVertices]; mout->mNumUVComponents[i] = minp->mNumUVComponents[i]; } for(unsigned int i = 0; minp->HasVertexColors(i); ++i) { mout->mColors[i] = new aiColor4D[mout->mNumVertices]; } mout->mNumVertices = mout->mNumFaces<<2u; for (unsigned int i = 0, v = 0, n = 0; i < minp->mNumFaces;++i) { const aiFace& face = minp->mFaces[i]; for (unsigned int a = 0; a < face.mNumIndices;++a) { // Get a clean new face. aiFace& faceOut = mout->mFaces[n++]; faceOut.mIndices = new unsigned int [faceOut.mNumIndices = 4]; // Spawn a new quadrilateral (ccw winding) for this original point between: // a) face centroid centroids[FLATTEN_FACE_IDX(t,i)].SortBack(mout,faceOut.mIndices[0]=v++); // b) adjacent edge on the left, seen from the centroid const Edge& e0 = edges[MAKE_EDGE_HASH(maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])], maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a==face.mNumIndices-1?0:a+1]) ])]; // fixme: replace with mod face.mNumIndices? // c) adjacent edge on the right, seen from the centroid const Edge& e1 = edges[MAKE_EDGE_HASH(maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])], maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[!a?face.mNumIndices-1:a-1]) ])]; // fixme: replace with mod face.mNumIndices? e0.edge_point.SortBack(mout,faceOut.mIndices[3]=v++); e1.edge_point.SortBack(mout,faceOut.mIndices[1]=v++); // d= original point P with distinct index i // F := 0 // R := 0 // n := 0 // for each face f containing i // F := F+ centroid of f // R := R+ midpoint of edge of f from i to i+1 // n := n+1 // // (F+2R+(n-3)P)/n const unsigned int org = maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])]; TouchedOVertex& ov = new_points[org]; if (!ov.first) { ov.first = true; const unsigned int* adj; unsigned int cnt; GET_ADJACENT_FACES_AND_CNT(org,adj,cnt); if (cnt < 3) { ov.second = Vertex(minp,face.mIndices[a]); } else { Vertex F,R; for (unsigned int o = 0; o < cnt; ++o) { ai_assert(adj[o] < totfaces); F += centroids[adj[o]]; // adj[0] is a global face index - search the face in the mesh list const aiMesh* mp = NULL; size_t nidx; if (adj[o] < moffsets[0].first) { mp = smesh[nidx=0]; } else { for (nidx = 1; nidx<= nmesh; ++nidx) { if (nidx == nmesh ||moffsets[nidx].first > adj[o]) { mp = smesh[--nidx]; break; } } } ai_assert(adj[o]-moffsets[nidx].first < mp->mNumFaces); const aiFace& f = mp->mFaces[adj[o]-moffsets[nidx].first]; bool haveit = false; // find our original point in the face for (unsigned int m = 0; m < f.mNumIndices; ++m) { if (maptbl[FLATTEN_VERTEX_IDX(nidx,f.mIndices[m])] == org) { // add *both* edges. this way, we can be sure that we add // *all* adjacent edges to R. In a closed shape, every // edge is added twice - so we simply leave out the // factor 2.f in the amove formula and get the right // result. const Edge& c0 = edges[MAKE_EDGE_HASH(org,maptbl[FLATTEN_VERTEX_IDX( nidx,f.mIndices[!m?f.mNumIndices-1:m-1])])]; // fixme: replace with mod face.mNumIndices? const Edge& c1 = edges[MAKE_EDGE_HASH(org,maptbl[FLATTEN_VERTEX_IDX( nidx,f.mIndices[m==f.mNumIndices-1?0:m+1])])]; // fixme: replace with mod face.mNumIndices? R += c0.midpoint+c1.midpoint; haveit = true; break; } } // this invariant *must* hold if the vertex-to-face adjacency table is valid ai_assert(haveit); if ( !haveit ) { DefaultLogger::get()->warn( "OBJ: no name for material library specified." ); } } const float div = static_cast<float>(cnt), divsq = 1.f/(div*div); ov.second = Vertex(minp,face.mIndices[a])*((div-3.f) / div) + R*divsq + F*divsq; } } ov.second.SortBack(mout,faceOut.mIndices[2]=v++); } } } } // end of scope for edges, freeing its memory // --------------------------------------------------------------------- // 7. Apply the next subdivision step. // --------------------------------------------------------------------- if (num != 1) { std::vector<aiMesh*> tmp(nmesh); InternSubdivide (out,nmesh,&tmp.front(),num-1); for (size_t i = 0; i < nmesh; ++i) { delete out[i]; out[i] = tmp[i]; } } }
/*! * Extracts and stores logical lines of code. * Determines and extract logical SLOC to place in the result variable * using addSLOC function. Each time the addSLOC function is called, * a new logical SLOC is added. This function assumes that the directive * is handled before it is called. * * \param result counter results * \param line processed physical line of code * \param lineBak original physical line of code * \param strLSLOC processed logical string * \param strLSLOCBak original logical string * \param paren_cnt count of parenthesis * \param loopWhiteSpace count of white space to determine loop ends */ void CPythonCounter::LSLOC(results* result, string line, size_t lineNumber, string lineBak, string &strLSLOC, string &strLSLOCBak, unsigned int &paren_cnt, UIntVector &loopWhiteSpace) { #define CONT_STR_LENGTH 18 string continuation_str[] = {"is", "in", "not", "+", "-", "*", "/", "=", "<", ">", "|", "&", "%", "^", "\\", "~", ",", "$"}; size_t start = 0; // starting index of the working string size_t i = 0, idx, strSize; int n; bool trunc_flag = false; unsigned int cnt = 0, numWS; string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$"; string tmp; // process: // paren_cnt is used with {} [] () // 1. check if the current char is in one of the parentheses // 2. if no, check if the line has : or ; (statement separators), except else: // 3. if yes, count and put the statement in the result // 4. if the line does not ends with a continuation string or a statement separator (handled) // and the line is not in one of the parentheses // then count and put the statement in the result // 5. physical count considers all lines executables (or directives, no declarations) // check for loop ends, new loops, and record white space in order to determine ends if (print_cmplx) { // check white space for loop ends if (loopWhiteSpace.size() > 0) { // get white space tmp = line; tmp = CUtil::TrimString(tmp, -1); numWS = (unsigned)(line.length() - tmp.length()); // check for loop ends for (n = (int)loopWhiteSpace.size() - 1; n >= 0; n--) { if (loopWhiteSpace.at(n) != numWS) break; else loopWhiteSpace.pop_back(); } } // check for loop keywords (for, while) cnt = 0; CUtil::CountTally(line, loop_keywords, cnt, 1, exclude, "", "", NULL); if (cnt > 0) { if (loopWhiteSpace.size() < 1) { // get white space tmp = line; tmp = CUtil::TrimString(tmp, -1); numWS = (unsigned)(line.length() - tmp.length()); } // add nested loop white space and record nested loop level for (i = 0; i < cnt; i++) { loopWhiteSpace.push_back(numWS); if ((unsigned int)result->cmplx_nestloop_count.size() < loopWhiteSpace.size()) result->cmplx_nestloop_count.push_back(1); else result->cmplx_nestloop_count[loopWhiteSpace.size()-1]++; } } } line = CUtil::TrimString(line); lineBak = CUtil::TrimString(lineBak); size_t line_length = line.length(); bool lineContinued = false; while (i < line_length) { switch (line[i]) { case '{': case '[': case '(': // parentheses opener paren_cnt++; break; case '}': case ']': case ')': // parentheses closer if (paren_cnt > 0) paren_cnt--; break; } // 2. if no parentheses enclosing, and if the char is a statement separator if (paren_cnt == 0 && (line[i] == ';' || line[i] == ':')) { tmp = CUtil::ClearRedundantSpaces(line); // if line[..i] is else: then exit the outer if if (tmp.rfind("else:") != tmp.length() - 5) { // 3. strSize = CUtil::TruncateLine(i + 1 - start, strLSLOC.length(), this->lsloc_truncate, trunc_flag); if (strSize > 0) { strLSLOC += line.substr(start, i); strLSLOCBak += lineBak.substr(start, i); } if (result->addSLOC(strLSLOCBak, lineNumber, trunc_flag)) { // increase logical SLOC here result->exec_lines[LOG]++; } strLSLOC = strLSLOCBak = ""; start = i + 1; } else lineContinued = true; } i++; } if (paren_cnt == 0) { // add logical SLOC if the line does not end with a continuation string/char if (!lineContinued) { for (i = 0; i < CONT_STR_LENGTH; i++) { if (continuation_str[i].length() == 1) { if (line[line_length - 1] == continuation_str[i][0]) { lineContinued = true; break; } } else { idx = CUtil::FindKeyword(line, continuation_str[i]); if (idx != string::npos && idx == line_length - continuation_str[i].length() - 1) { lineContinued = true; break; } } } } if (!lineContinued) { strSize = CUtil::TruncateLine(line_length - start, strLSLOC.length(), this->lsloc_truncate, trunc_flag); if (strSize > 0) { strLSLOC += line.substr(start, line_length); strLSLOCBak += lineBak.substr(start, line_length); } if (result->addSLOC(strLSLOCBak, lineNumber, trunc_flag)) { // increase logical SLOC here result->exec_lines[LOG]++; } strLSLOC = strLSLOCBak = ""; } else { tmp = CUtil::TrimString(line.substr(start, line_length - start)); strSize = CUtil::TruncateLine(tmp.length(), strLSLOC.length(), this->lsloc_truncate, trunc_flag); if (strSize > 0) { strLSLOC += tmp.substr(0, strSize); tmp = CUtil::TrimString(lineBak.substr(start, line_length - start)); strLSLOCBak += tmp.substr(0, strSize); } } } result->exec_lines[PHY]++; }
EStatusCode CFFEmbeddedFontWriter::WriteEncodings(const UIntVector& inSubsetGlyphIDs) { // if it's a CID. don't bother with encodings (marks as 0) if(mIsCID) { mEncodingPosition = 0; return PDFHummus::eSuccess; } // not CID, write encoding, according to encoding values from the original font EncodingsInfo* encodingInfo = mOpenTypeInput.mCFF.mTopDictIndex[0].mEncoding; if(encodingInfo->mEncodingStart <= 1) { mEncodingPosition = encodingInfo->mEncodingStart; return PDFHummus::eSuccess; } else { // original font had custom encoding, let's subset it according to just the glyphs we // actually have. but cause i'm lazy i'll just do the first format. // figure out if we got supplements UIntVector::const_iterator it = inSubsetGlyphIDs.begin(); ByteAndUShortList supplements; for(; it != inSubsetGlyphIDs.end();++it) { // don't be confused! the supplements is by SID! not GID! unsigned short sid = mOpenTypeInput.mCFF.GetGlyphSID(0,*it); UShortToByteList::iterator itSupplements = encodingInfo->mSupplements.find(sid); if(itSupplements != encodingInfo->mSupplements.end()) { ByteList::iterator itMoreEncoding = itSupplements->second.begin(); for(; itMoreEncoding != itSupplements->second.end(); ++itMoreEncoding) supplements.push_back(ByteAndUShort(*itMoreEncoding,sid)); } } mEncodingPosition = mFontFileStream.GetCurrentPosition(); if(supplements.size() > 0) mPrimitivesWriter.WriteCard8(0x80); else mPrimitivesWriter.WriteCard8(0); // assuming that 0 is in the subset glyphs IDs, which does not require encoding // get the encodings count Byte encodingGlyphsCount = std::min((Byte)(inSubsetGlyphIDs.size()-1),encodingInfo->mEncodingsCount); mPrimitivesWriter.WriteCard8(encodingGlyphsCount); for(Byte i=0; i < encodingGlyphsCount;++i) { if(inSubsetGlyphIDs[i+1] < encodingInfo->mEncodingsCount) mPrimitivesWriter.WriteCard8(encodingInfo->mEncoding[inSubsetGlyphIDs[i+1]-1]); else mPrimitivesWriter.WriteCard8(0); } if(supplements.size() > 0) { mPrimitivesWriter.WriteCard8(Byte(supplements.size())); ByteAndUShortList::iterator itCollectedSupplements = supplements.begin(); for(; itCollectedSupplements != supplements.end(); ++itCollectedSupplements) { mPrimitivesWriter.WriteCard8(itCollectedSupplements->first); mPrimitivesWriter.WriteCard16(itCollectedSupplements->second); } } } return mPrimitivesWriter.GetInternalState(); }