void drawPatch(GLfloat *ptrData, GLuint &ptrIndex, GLfloat p1[3], GLfloat p2[3], GLfloat p3[3], int level, GLuint *count) { int i; if (level > 0) { GLfloat q1[3],q2[3],q3[3]; // sub-vertices for (i=0; i<3; i++) { q1[i] = 0.5f*(p1[i]+p2[i]); q2[i] = 0.5f*(p2[i]+p3[i]); q3[i] = 0.5f*(p3[i]+p1[i]); } GLfloat length1 = (GLfloat)(1.0/sqrt(q1[0]*q1[0]+q1[1]*q1[1]+q1[2]*q1[2])); GLfloat length2 = (GLfloat)(1.0/sqrt(q2[0]*q2[0]+q2[1]*q2[1]+q2[2]*q2[2])); GLfloat length3 = (GLfloat)(1.0/sqrt(q3[0]*q3[0]+q3[1]*q3[1]+q3[2]*q3[2])); for (i=0; i<3; i++) { q1[i] *= length1; q2[i] *= length2; q3[i] *= length3; } drawPatch(ptrData,ptrIndex,p1,q1,q3,level-1,count); drawPatch(ptrData,ptrIndex,q1,p2,q2,level-1,count); drawPatch(ptrData,ptrIndex,q1,q2,q3,level-1,count); drawPatch(ptrData,ptrIndex,q3,q2,p3,level-1,count); } else { if( count ) { *count += 3; } else { EmitVertex(ptrData,ptrIndex,p1[0],p1[1],p1[2]); // vertex EmitVertex(ptrData,ptrIndex,p1[0],p1[1],p1[2]); // normal EmitVertex(ptrData,ptrIndex,p2[0],p2[1],p2[2]); // vertex EmitVertex(ptrData,ptrIndex,p2[0],p2[1],p2[2]); // normal EmitVertex(ptrData,ptrIndex,p3[0],p3[1],p3[2]); // vertex EmitVertex(ptrData,ptrIndex,p3[0],p3[1],p3[2]); // normal } } }
void drawVarAllCent (double, double highPt, TH1D* hvar, TString var,TString varName, TCut addCut, bool doLog, TString subName,bool onleMC, float maxY ) { TCanvas* c2 = new TCanvas(Form("c2_%s%s",var.Data(),subName.Data()),"",1000,400); makeMultiPanelCanvas(c2,3,1,0.0,0.0,0.2,0.15,0.02); for ( int icent = 1 ; icent<=3 ; icent++) { int lowCent = centBin_std[icent-1]; int highCent = centBin_std[icent]-1; c2->cd(4-icent); drawVariable(lowCent,highCent,60,10000,hvar, var, addCut,doLog,onleMC, maxY); if (doLog ) gPad->SetLogy(); drawText(Form("%.0f %% - %.0f %%", float((float)lowCent*2.5), float((float)(highCent+1)*2.5)),0.6580963,0.9069118,1,16); // drawText("Photon E_{T} > 60GeV",0.3680963,0.6569118,1,15); if ( icent == 1 ) { if (!onleMC) drawCMS2011(0.338,0.906,84,16); } if (icent==2) { TH1D* data = new TH1D("data11","",1,0,1); data->Sumw2(); TH1D* mcSig = new TH1D("mcSig11","",1,0,1); mcStyle(mcSig); TH1D* mcBkg = new TH1D("mcBkg11","",1,0,1); dijetStyle(mcBkg); TLegend* leg1 = new TLegend(0.1586395,0.7137837,0.9992263,0.9626509,NULL,"brNDC"); easyLeg(leg1,varName.Data()); if( !onleMC) leg1->AddEntry(data,"Data","pl"); leg1->AddEntry(mcSig,"MC #gamma-jet + HYDJET","fl"); leg1->AddEntry(mcBkg,"MC dijet Background","fl"); leg1->Draw(); } drawPatch(0,0,0.05,0.14,0,1001,"NDC"); drawPatch(0.93,0.05,1.01,0.14,0,1001,"NDC"); } if (subName ==""){ c2->SaveAs(Form("%s_MCvsDATA_allCent.pdf",var.Data())); c2->SaveAs(Form("%s_MCvsDATA_allCent.gif",var.Data())); } else { c2->SaveAs(Form("%s_MCvsDATA_allCent.pdf",subName.Data())); c2->SaveAs(Form("%s_MCvsDATA_allCent.gif",subName.Data())); } }
void plotSubLeadingJetAllCent_onlyImbalancedJets() { TCanvas *c1 = new TCanvas("c1","",1250,530); makeMultiPanelCanvas(c1,3,1,0.0,0.0,0.2,0.15,0.02); c1->cd(1); plotLeadingJet(2,"data.root","pythia.root","mix.root",true,false,false); gPad->SetLogy(); drawText("30-100%",0.25,0.24); drawPatch(0.976,0.0972,1.1,0.141); c1->cd(2); plotLeadingJet(1,"data.root","pythia.root","mix.root",true,true,false); gPad->SetLogy(); drawText("10-30%",0.10,0.24); drawPatch(-0.00007,0.0972,0.0518,0.141); drawPatch(0.976,0.0972,1.1,0.141); c1->cd(3); plotLeadingJet(0,"data.root","pythia.root","mix.root",true,false,true); gPad->SetLogy(); drawText("0-10%",0.10,0.24); drawPatch(-0.00007,0.0972,0.0518,0.141); TLatex *cms = new TLatex(81,1.8,"CMS Preliminary"); cms->SetTextFont(63); cms->SetTextSize(18); cms->Draw(); // TLatex *imb = new TLatex(150,0.18,"(p_{T}^{j1}-p_{T}^{j2})/(p_{T}^{j1}+p_{T}^{j2})>0.3"); TLatex *imb = new TLatex(81,0.27,"A_{J} > 0.3"); imb->SetTextFont(63); imb->SetTextSize(18); imb->Draw(); TLatex *lumi = new TLatex(111,1.8,"#intL dt = 6.7 #mub^{-1}"); lumi->SetTextFont(63); lumi->SetTextSize(15); lumi->Draw(); c1->Print("./fig/dijet_subleadingjet_all_cent_onlyImbalancedJets_20101127_v0.gif"); c1->Print("./fig/dijet_subleadingjet_all_cent_onlyImbalancedJets_20101127_v0.eps"); c1->Print("./fig/dijet_subleadingjet_all_cent_onlyImbalancedJets_20101127_v0.pdf"); }
void plotBackgroundSystematics(){ TCanvas *c1 = new TCanvas("c1","",1650,430); makeMultiPanelCanvas(c1,5,1,0.0,0.0,0.2,0.15,0.02); c1->cd(1); plotRatio(4,"mix.root","mix.root","pythia.root",false,false,false); drawText("50-100%",0.76,0.24); drawPatch(0.976,0.0972,1.1,0.171); gPad->SetLeftMargin(0.25); gPad->SetBottomMargin(0.18); c1->cd(2); plotRatio(3,"mix.root","mix.root","pythia.root",false,false,false); drawText("30-50%",0.75,0.24); drawPatch(-0.00007,0.0972,0.0518,0.171); drawPatch(0.976,0.0972,1.1,0.171); gPad->SetBottomMargin(0.18); c1->cd(3); plotRatio(2,"mix.root","mix.root","pythia.root",false,true,false); drawText("20-30%",0.75,0.24); drawPatch(-0.00007,0.0972,0.0518,0.171); gPad->SetBottomMargin(0.18); drawPatch(0.976,0.0972,1.1,0.171); c1->cd(4); plotRatio(1,"mix.root","mix.root","pythia.root",false,false,false); drawText("10-20%",0.75,0.24); drawPatch(-0.00007,0.0972,0.0518,0.171); gPad->SetBottomMargin(0.18); drawPatch(0.976,0.0972,1.1,0.171); c1->cd(5); plotRatio(0,"mix.root","mix.root","pythia.root",false,false,true); drawText("0-10%",0.75,0.24); gPad->SetBottomMargin(0.18); drawPatch(-0.00007,0.0972,0.0518,0.171); TLatex *cms = new TLatex(0.086,4.5,"CMS Preliminary"); cms->SetTextFont(63); cms->SetTextSize(18); cms->Draw(); TLatex *lumi = new TLatex(0.15,4.1,"#intL dt = 7 #mub^{-1}"); lumi->SetTextFont(63); lumi->SetTextSize(15); // lumi->Draw(); c1->Print("./fig/ratio_pythiaToMix_20101207_v0.gif"); c1->Print("./fig/ratio_pythiaToMix_20101207_v0.eps"); c1->Print("./fig/ratio_pythiaToMix_20101207_v0.pdf"); }
void plotLeadingEtaBalance_AllCent(){ TCanvas *c1 = new TCanvas("c1","",1250,530); makeMultiPanelCanvas(c1,3,1,0.0,0.0,0.2,0.15,0.02); c1->cd(1); plotDeltaPhi(2,"data.root","pythia.root","mix.root",true,false,false); gPad->SetLogy(); drawText("30-100%",0.77,0.66); drawPatch(0.976,0.0972,1.1,0.141); c1->cd(2); plotDeltaPhi(1,"data.root","pythia.root","mix.root",true,true,false); gPad->SetLogy(); drawText("10-30%",0.75,0.66); drawPatch(-0.00007,0.0972,0.0518,0.141); drawPatch(0.976,0.0972,1.1,0.141); c1->cd(3); plotDeltaPhi(0,"data.root","pythia.root","mix.root",true,false,true); gPad->SetLogy(); drawText("0-10%",0.75,0.66); drawPatch(-0.00007,0.0972,0.0518,0.141); TLatex *cms = new TLatex(-2.,2.49,"CMS Preliminary"); cms->SetTextFont(63); cms->SetTextSize(18); cms->Draw(); TLatex *lumi = new TLatex(0.3,2.49,"#intL dt = 6.7 #mub^{-1}"); lumi->SetTextFont(63); lumi->SetTextSize(15); lumi->Draw(); TLatex *aj= new TLatex(-2.,0.2,"A_{J} < 0.3"); aj->SetTextFont(63); aj->SetTextSize(18); aj->Draw(); c1->Print("./fig/dijet_leadingEta_balance_all_cent_20101126_v0.gif"); c1->Print("./fig/dijet_leadingEta_balance_all_cent_20101126_v0.eps"); c1->Print("./fig/dijet_leadingEta_balance_all_cent_20101126_v0.pdf"); }
void getBatchFaceCount( // input const double *FM, int fNum, const double *VM, int vNum, const double *objCenterV, double maxRadius, const double *majorAxisM, const double *lightDirM, int lightNum, int maxHeight, int maxWidth, unsigned int channelModFactor, // output void *FacePixelCountM) { int i; GLubyte *imageBuffer = (GLubyte *) mxMalloc(maxHeight * maxWidth * 3); GLuint batchList = createDisplayList(FM, fNum, VM, vNum, channelModFactor); //memset(FacePixelCountM, 0, sizeof(double) * fNum * lightNum); printf("Facet Number: %d, Vertex Number: %d\nProjecting images: \n", fNum, vNum); float screenScale; // make sure that maxHeight always >= maxWidth if (maxHeight < maxWidth) { int temp = maxHeight; maxHeight = maxWidth; maxWidth = temp; } for (i = 0; i < lightNum; i++) { printf(" %d ", i); if (i % 16 == 15) { printf("\n"); } orthoCameraSetup(objCenterV, lightDirM + 3*i, maxRadius, majorAxisM, maxHeight, maxWidth, screenScale); drawPatch(batchList, imageBuffer, maxHeight, maxWidth); extractFaceCount(imageBuffer, channelModFactor, maxHeight, maxWidth, fNum, i%(32), (unsigned int*) FacePixelCountM + i/32 * fNum); } printf("\n"); mxFree(imageBuffer); }
void Patch::draw() { if (isMouseOver()) { hover = true; } else { hover = false; } ofPushStyle(); ofSetColor(150.0f); ofEnableSmoothing(); ofEnableAntiAliasing(); ofSetLineWidth(2.0f); if (port_connect) { ofLine(line_start, ofPoint(ofGetMouseX(), ofGetMouseY())); } // also draw all connections for (int i = 0; i < connections.size(); i++) { ofLine(connections[i]->from->cp, connections[i]->to->cp); } ofPopStyle(); switch (type) { case PATCH: drawPatch(); break; case UI_BUTTON: drawButton(); break; case UI_FIXED_BUTTON: drawFixedButton(); break; }; }
void drawSphere(GLfloat *ptrData, GLuint &ptrIndex, int sphere_quality, GLuint *count) { // icosahedron data for an icosahedron of radius 1.0 #define ICX 0.525731112119133606f #define ICZ 0.850650808352039932f static GLfloat idata[12][3] = { {-ICX, 0, ICZ}, {ICX, 0, ICZ}, {-ICX, 0, -ICZ}, {ICX, 0, -ICZ}, {0, ICZ, ICX}, {0, ICZ, -ICX}, {0, -ICZ, ICX}, {0, -ICZ, -ICX}, {ICZ, ICX, 0}, {-ICZ, ICX, 0}, {ICZ, -ICX, 0}, {-ICZ, -ICX, 0} }; static int index[20][3] = { {0, 4, 1}, {0, 9, 4}, {9, 5, 4}, {4, 5, 8}, {4, 8, 1}, {8, 10, 1}, {8, 3, 10}, {5, 3, 8}, {5, 2, 3}, {2, 7, 3}, {7, 10, 3}, {7, 6, 10}, {7, 11, 6}, {11, 0, 6}, {0, 1, 6}, {6, 1, 10}, {9, 0, 11}, {9, 11, 2}, {9, 2, 5}, {7, 2, 11}, }; for (int i=0; i<20; i++) { drawPatch(ptrData, ptrIndex, &idata[index[i][2]][0],&idata[index[i][1]][0], &idata[index[i][0]][0],sphere_quality, count); } }
// ###################################################################### void SimulationViewerStats::save1(const ModelComponentSaveInfo& sinfo) { // Use a LINFO here since we are already slowed down by writing // stats, we should at least have a short debug on this fact LINFO("SAVING STATS TO %s",itsStatsFname.getVal().c_str()); // Lock the file. We put this here to support multi-process in the // future. However, this will not work on NFS mounts. struct flock fl; int fd; lockFile(itsStatsFname.getVal().c_str(),fd,fl); // Since this is more or less debug info we open and flush every iteration. // rather than once each run. std::ofstream statsFile; statsFile.open(itsStatsFname.getVal().c_str(),std::ios_base::app); // get the OFS to save to, assuming sinfo is of type // SimModuleSaveInfo (will throw a fatal exception otherwise): nub::ref<FrameOstream> ofs = dynamic_cast<const SimModuleSaveInfo&>(sinfo).ofs; // also get the SimEventQueue: SimEventQueue *q = dynamic_cast<const SimModuleSaveInfo&>(sinfo).q; // initialize our stats dump file if desired: if(itsFrameIdx == 0) { rutz::shared_ptr<SimReqVCXmaps> vcxm(new SimReqVCXmaps(this)); q->request(vcxm); // VisualCortex is now filling-in the maps... if (itsStatsFname.getVal().size()) { itsStatsFile = new std::ofstream(itsStatsFname.getVal().c_str()); if (itsStatsFile->is_open() == false) LFATAL("Failed to open '%s' for writing.", itsStatsFname.getVal().c_str()); // dump the settings of the model: getRootObject()->printout(*itsStatsFile, "# "); // list all our channels: //LFATAL("FIXME"); // also get the SimEventQueue: rutz::shared_ptr<ChannelMaps> chm = vcxm->channelmaps(); uint numSubmaps = chm->numSubmaps(); *itsStatsFile << "# CHANNELS: "; for(uint i = 0; i < numSubmaps; i++) { NamedImage<float> smap = chm->getRawCSmap(i); *itsStatsFile << smap.name() << ", "; } *itsStatsFile << std::endl; } } // We flush frequently since this output is debuggy in nature or it's being used // to collect information which needs assurance of accuracy for instance in // RSVP analysis. It is better to err on the side of caution. (*itsStatsFile).flush(); (*itsStatsFile).close(); // get the basic input frame info if (SeC<SimEventInputFrame> e = q->check<SimEventInputFrame>(this)) { itsSizeX = e->frame().getWidth(); itsSizeY = e->frame().getHeight(); itsFrameNumber = (unsigned int)e->frameNum(); itsFrameIdx = itsFrameNumber; } else { itsFrameNumber = itsFrameIdx; itsFrameIdx++; } // get the latest input frame: // Since we are only using it's basic statistics (Height / Width) , we don't care about it's // blackboard status. Use SEQ_ANY then. Otherwise, this will not fetch at any rate. Image< PixRGB<byte> > input; if (SeC<SimEventRetinaImage> e = q->check<SimEventRetinaImage>(this,SEQ_ANY)) input = e->frame().colorByte(); else LINFO("No input? Check the SimEventCue."); // Get the current frame number or keep track on your own /* if (SeC<SimEventInputFrame> e = q->check<SimEventInputFrame>(this)) itsFrameIdx = e->frameNum(); else itsFrameIdx++; */ // get the latest raw AGM: Image<float> agm; if (SeC<SimEventAttentionGuidanceMapOutput> e = q->check<SimEventAttentionGuidanceMapOutput>(this)) agm = e->agm(1.0F); else LINFO("No AGM? Check the SimEventCue."); // if we are missing input or agm, return: // We also need to warn so that we know why the stats file may be empty bool quit = false; if (input.initialized() == false) { LINFO("WARNING!!! Input seems not to be initialized, so detailed stats cannot be saved."); quit = true; } if(agm.initialized() == false) { LINFO("WARNING!!! NO Attention Guidance MAP \"AGM\" so detailed stats cannot be saved."); quit = true; } if(quit == true) return; // update the trajectory: Image< PixRGB<byte> > res; const int w = input.getWidth(); // save image results? if so let's prepare it if (itsSaveXcombo.getVal() || itsSaveYcombo.getVal()) { Image<float> nagm = getMap(*q); res = colGreyCombo(input, nagm, itsSaveXcombo.getVal(), itsDisplayInterp.getVal()); } // if we are saving single channel stats save saliency stats using a compatable format // SEE: SingleChannel.C / saveStats(..) for more info on format if (itsGetSingleChannelStats.getVal()) saveCompat(agm); // Save a bunch of stats? if (statsFile) { // start with the current simulation time: statsFile <<std::endl<<"= "<<q->now().msecs() <<" # time of frame in ms"<<std::endl; // get min/max/avg and stdev and number of peaks in AGM: float mi, ma, av; getMinMaxAvg(agm, mi, ma, av); double sdev = stdev(agm); double peaksum; int npeaks = findPeaks(agm, 0.0f, 255.0f, peaksum); // find the location of max in the AGM, at scale of original input: float maxval; Point2D<int> maxloc; findMax(agm, maxloc, maxval); float scale = float(w) / float(agm.getWidth()); maxloc.i = int(maxloc.i * scale + 0.4999F); maxloc.j = int(maxloc.j * scale + 0.4999F); if (res.initialized()) { drawPatch(res, maxloc, 4, COL_YELLOW); drawPatch(res, maxloc + Point2D<int>(w, 0), 4, COL_YELLOW); } // find the location of min in the AGM, at scale of original input: float minval; Point2D<int> minloc; findMin(agm, minloc, minval); minloc.i = int(minloc.i * scale + 0.4999F); minloc.j = int(minloc.j * scale + 0.4999F); if (res.initialized()) { drawPatch(res, minloc, 4, COL_GREEN); drawPatch(res, minloc + Point2D<int>(w, 0), 4, COL_GREEN); } // save some stats for that location: statsFile <<maxloc.i<<' '<<maxloc.j<<' '<<minloc.i<<' ' <<minloc.j<<' '<<ma<<' '<<mi<<' '<<av<<' '<<sdev <<' '<<npeaks<<' '<<peaksum <<" # Xmax Ymax Xmin Ymin max min avg std npeaks peaksum" <<std::endl; // build a vector of points where we will save samples. First is // the max, second the min, then a bunch of random locations: std::vector<Point2D<int> > loc; loc.push_back(maxloc); loc.push_back(minloc); for (uint n = 0; n < 100; n ++) loc.push_back(Point2D<int>(randomUpToNotIncluding(input.getWidth()), randomUpToNotIncluding(input.getHeight()))); // Get all the conspicuity maps: ImageSet<float> cmap; //LFATAL("FIXME"); rutz::shared_ptr<SimReqVCXmaps> vcxm(new SimReqVCXmaps(this)); q->request(vcxm); // VisualCortex is now filling-in the maps... rutz::shared_ptr<ChannelMaps> chm = vcxm->channelmaps(); uint numSubmaps = chm->numSubmaps(); for(uint i=0;i < numSubmaps; i++) { NamedImage<float> tempMap = chm->getRawCSmap(i); Image<float> m = tempMap; cmap.push_back(m); // also store sample points at the min/max locations: Point2D<int> p; float v; findMax(m, p, v); loc.push_back(p); findMin(m, p, v); loc.push_back(p); } /* for (uint i = 0; i < itsBrain->getVC()->numChans(); i ++) { Image<float> m = itsBrain->getVC()->subChan(i)->getOutput(); cmap.push_back(m); // also store sample points at the min/max locations: Point2D<int> p; float v; findMax(m, p, v); loc.push_back(p); findMin(m, p, v); loc.push_back(p); } */ // Go over all sample points and save feature map and // conspicuity map values at those locations: for (uint i = 0; i < loc.size(); i ++) { Point2D<int> p = loc[i]; Point2D<int> pp(int(p.i / scale), int(p.j / scale)); statsFile <<p.i<<' '<<p.j<<" "; // do the conspicuity maps first. Since they are all at the // scale of the AGM, we use pp: for (uint j = 0; j < cmap.size(); j ++) { if((int(p.i / scale) < agm.getWidth()) && (int(p.j / scale) < agm.getHeight())) { (statsFile)<<cmap[j].getVal(pp)<<' '; (statsFile)<<" "; } else { (statsFile)<<"-1"<<' '; (statsFile)<<" "; } } // now the feature maps, we use coordinates p: /* TOO BOGUS - disabled for now std::vector<double> f; itsBrain->getVC()->getFeatures(p, f); for (uint j = 0; j < f.size(); j ++) (*statsFile)<<f[j]<<' '; */ statsFile <<"# features "<<i<<" at ("<<p.i <<", "<<p.j<<')'<<std::endl; } } statsFile.flush(); statsFile.close(); unlockFile(itsStatsFname.getVal().c_str(),fd,fl); // save results? if (res.initialized()) ofs->writeRGB(res, "T", FrameInfo("SimulationViewerStats trajectory", SRC_POS)); // Should we compute attention gate stats // If we have AG stats we will save the basic LAM stats anyways if(itsComputeAGStats.getVal()) computeAGStats(*q); else if (SeC<SimEventAttentionGateOutput> ag = q->check<SimEventAttentionGateOutput>(this)) computeLAMStats(ag->lam()); //! Save the overlap image if(itsOverlap.initialized()) ofs->writeRGB(itsOverlap, "AG-STAT-MASK", FrameInfo("Stats mask overlap", SRC_POS)); if(itsVisualSegments.initialized()) ofs->writeRGB(itsVisualSegments, "AG-STAT-SEGS", FrameInfo("Stats segments", SRC_POS)); if(itsVisualCandidates.initialized()) ofs->writeGray(itsVisualCandidates, "AG-STAT-CAND", FrameInfo("Stats candidates", SRC_POS)); }
namespace SkRecords { // FIXME: SkBitmaps are stateful, so we need to copy them to play back in multiple threads. static SkBitmap shallow_copy(const SkBitmap& bitmap) { return bitmap; } // NoOps draw nothing. template <> void Draw::draw(const NoOp&) {} #define DRAW(T, call) template <> void Draw::draw(const T& r) { fCanvas->call; } DRAW(Restore, restore()); DRAW(Save, save()); DRAW(SaveLayer, saveLayer(r.bounds, r.paint, r.flags)); DRAW(PopCull, popCull()); DRAW(PushCull, pushCull(r.rect)); DRAW(Clear, clear(r.color)); DRAW(Concat, concat(r.matrix)); DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix))); DRAW(ClipPath, clipPath(r.path, r.op, r.doAA)); DRAW(ClipRRect, clipRRect(r.rrect, r.op, r.doAA)); DRAW(ClipRect, clipRect(r.rect, r.op, r.doAA)); DRAW(ClipRegion, clipRegion(r.region, r.op)); DRAW(DrawBitmap, drawBitmap(shallow_copy(r.bitmap), r.left, r.top, r.paint)); DRAW(DrawBitmapMatrix, drawBitmapMatrix(shallow_copy(r.bitmap), r.matrix, r.paint)); DRAW(DrawBitmapNine, drawBitmapNine(shallow_copy(r.bitmap), r.center, r.dst, r.paint)); DRAW(DrawBitmapRectToRect, drawBitmapRectToRect(shallow_copy(r.bitmap), r.src, r.dst, r.paint, r.flags)); DRAW(DrawDRRect, drawDRRect(r.outer, r.inner, r.paint)); DRAW(DrawOval, drawOval(r.oval, r.paint)); DRAW(DrawPaint, drawPaint(r.paint)); DRAW(DrawPath, drawPath(r.path, r.paint)); DRAW(DrawPatch, drawPatch(r.cubics, r.colors, r.texCoords, r.xmode.get(), r.paint)); DRAW(DrawPicture, drawPicture(r.picture, r.matrix, r.paint)); DRAW(DrawPoints, drawPoints(r.mode, r.count, r.pts, r.paint)); DRAW(DrawPosText, drawPosText(r.text, r.byteLength, r.pos, r.paint)); DRAW(DrawPosTextH, drawPosTextH(r.text, r.byteLength, r.xpos, r.y, r.paint)); DRAW(DrawRRect, drawRRect(r.rrect, r.paint)); DRAW(DrawRect, drawRect(r.rect, r.paint)); DRAW(DrawSprite, drawSprite(shallow_copy(r.bitmap), r.left, r.top, r.paint)); DRAW(DrawText, drawText(r.text, r.byteLength, r.x, r.y, r.paint)); DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, r.matrix, r.paint)); DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors, r.xmode.get(), r.indices, r.indexCount, r.paint)); #undef DRAW // This is an SkRecord visitor that fills an SkBBoxHierarchy. // // The interesting part here is how to calculate bounds for ops which don't // have intrinsic bounds. What is the bounds of a Save or a Translate? // // We answer this by thinking about a particular definition of bounds: if I // don't execute this op, pixels in this rectangle might draw incorrectly. So // the bounds of a Save, a Translate, a Restore, etc. are the union of the // bounds of Draw* ops that they might have an effect on. For any given // Save/Restore block, the bounds of the Save, the Restore, and any other // non-drawing ("control") ops inside are exactly the union of the bounds of // the drawing ops inside that block. // // To implement this, we keep a stack of active Save blocks. As we consume ops // inside the Save/Restore block, drawing ops are unioned with the bounds of // the block, and control ops are stashed away for later. When we finish the // block with a Restore, our bounds are complete, and we go back and fill them // in for all the control ops we stashed away. class FillBounds : SkNoncopyable { public: FillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) : fBounds(record.count()) { // Calculate bounds for all ops. This won't go quite in order, so we'll need // to store the bounds separately then feed them in to the BBH later in order. fCTM.setIdentity(); for (fCurrentOp = 0; fCurrentOp < record.count(); fCurrentOp++) { record.visit<void>(fCurrentOp, *this); } // If we have any lingering unpaired Saves, simulate restores to make // sure all ops in those Save blocks have their bounds calculated. while (!fSaveStack.isEmpty()) { this->popSaveBlock(); } // Any control ops not part of any Save/Restore block draw everywhere. while (!fControlIndices.isEmpty()) { this->popControl(SkIRect::MakeLargest()); } // Finally feed all stored bounds into the BBH. They'll be returned in this order. SkASSERT(NULL != bbh); for (uintptr_t i = 0; i < record.count(); i++) { if (!fBounds[i].isEmpty()) { bbh->insert((void*)i, fBounds[i], true/*ok to defer*/); } } bbh->flushDeferredInserts(); } template <typename T> void operator()(const T& r) { this->updateCTM(r); this->trackBounds(r); } private: struct SaveBounds { int controlOps; // Number of control ops in this Save block, including the Save. SkIRect bounds; // Bounds of everything in the block. }; template <typename T> void updateCTM(const T&) { /* most ops don't change the CTM */ } void updateCTM(const Restore& r) { fCTM = r.matrix; } void updateCTM(const SetMatrix& r) { fCTM = r.matrix; } void updateCTM(const Concat& r) { fCTM.preConcat(r.matrix); } // The bounds of these ops must be calculated when we hit the Restore // from the bounds of the ops in the same Save block. void trackBounds(const Save&) { this->pushSaveBlock(); } // TODO: bounds of SaveLayer may be more complicated? void trackBounds(const SaveLayer&) { this->pushSaveBlock(); } void trackBounds(const Restore&) { fBounds[fCurrentOp] = this->popSaveBlock(); } void trackBounds(const Concat&) { this->pushControl(); } void trackBounds(const SetMatrix&) { this->pushControl(); } void trackBounds(const ClipRect&) { this->pushControl(); } void trackBounds(const ClipRRect&) { this->pushControl(); } void trackBounds(const ClipPath&) { this->pushControl(); } void trackBounds(const ClipRegion&) { this->pushControl(); } // For all other ops, we can calculate and store the bounds directly now. template <typename T> void trackBounds(const T& op) { fBounds[fCurrentOp] = this->bounds(op); this->updateSaveBounds(fBounds[fCurrentOp]); } // TODO: remove this trivially-safe default when done bounding all ops template <typename T> SkIRect bounds(const T&) { return SkIRect::MakeLargest(); } void pushSaveBlock() { // Starting a new Save block. Push a new entry to represent that. SaveBounds sb = { 0, SkIRect::MakeEmpty() }; fSaveStack.push(sb); this->pushControl(); } SkIRect popSaveBlock() { // We're done the Save block. Apply the block's bounds to all control ops inside it. SaveBounds sb; fSaveStack.pop(&sb); while (sb.controlOps --> 0) { this->popControl(sb.bounds); } // This whole Save block may be part another Save block. this->updateSaveBounds(sb.bounds); // If called from a real Restore (not a phony one for balance), it'll need the bounds. return sb.bounds; } void pushControl() { fControlIndices.push(fCurrentOp); if (!fSaveStack.isEmpty()) { fSaveStack.top().controlOps++; } } void popControl(const SkIRect& bounds) { fBounds[fControlIndices.top()] = bounds; fControlIndices.pop(); } void updateSaveBounds(const SkIRect& bounds) { // If we're in a Save block, expand its bounds to cover these bounds too. if (!fSaveStack.isEmpty()) { fSaveStack.top().bounds.join(bounds); } } SkIRect bounds(const NoOp&) { return SkIRect::MakeEmpty(); } // NoOps don't draw anywhere. SkAutoTMalloc<SkIRect> fBounds; // One for each op in the record. SkMatrix fCTM; unsigned fCurrentOp; SkTDArray<SaveBounds> fSaveStack; SkTDArray<unsigned> fControlIndices; }; } // namespace SkRecords
namespace SkRecords { // NoOps draw nothing. template <> void Draw::draw(const NoOp&) {} #define DRAW(T, call) template <> void Draw::draw(const T& r) { fCanvas->call; } DRAW(Restore, restore()); DRAW(Save, save()); DRAW(SaveLayer, saveLayer(SkCanvas::SaveLayerRec(r.bounds, r.paint, r.backdrop.get(), r.saveLayerFlags))); DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix))); DRAW(Concat, concat(r.matrix)); DRAW(Translate, translate(r.dx, r.dy)); DRAW(ClipPath, clipPath(r.path, r.opAA.op, r.opAA.aa)); DRAW(ClipRRect, clipRRect(r.rrect, r.opAA.op, r.opAA.aa)); DRAW(ClipRect, clipRect(r.rect, r.opAA.op, r.opAA.aa)); DRAW(ClipRegion, clipRegion(r.region, r.op)); #ifdef SK_EXPERIMENTAL_SHADOWING DRAW(TranslateZ, SkCanvas::translateZ(r.z)); #else template <> void Draw::draw(const TranslateZ& r) { } #endif DRAW(DrawArc, drawArc(r.oval, r.startAngle, r.sweepAngle, r.useCenter, r.paint)); DRAW(DrawDRRect, drawDRRect(r.outer, r.inner, r.paint)); DRAW(DrawImage, drawImage(r.image.get(), r.left, r.top, r.paint)); template <> void Draw::draw(const DrawImageLattice& r) { SkCanvas::Lattice lattice; lattice.fXCount = r.xCount; lattice.fXDivs = r.xDivs; lattice.fYCount = r.yCount; lattice.fYDivs = r.yDivs; lattice.fFlags = (0 == r.flagCount) ? nullptr : r.flags; lattice.fBounds = &r.src; fCanvas->drawImageLattice(r.image.get(), lattice, r.dst, r.paint); } DRAW(DrawImageRect, legacy_drawImageRect(r.image.get(), r.src, r.dst, r.paint, r.constraint)); DRAW(DrawImageNine, drawImageNine(r.image.get(), r.center, r.dst, r.paint)); DRAW(DrawOval, drawOval(r.oval, r.paint)); DRAW(DrawPaint, drawPaint(r.paint)); DRAW(DrawPath, drawPath(r.path, r.paint)); DRAW(DrawPatch, drawPatch(r.cubics, r.colors, r.texCoords, r.xmode, r.paint)); DRAW(DrawPicture, drawPicture(r.picture.get(), &r.matrix, r.paint)); #ifdef SK_EXPERIMENTAL_SHADOWING DRAW(DrawShadowedPicture, drawShadowedPicture(r.picture.get(), &r.matrix, r.paint, r.params)); #else template <> void Draw::draw(const DrawShadowedPicture& r) { } #endif DRAW(DrawPoints, drawPoints(r.mode, r.count, r.pts, r.paint)); DRAW(DrawPosText, drawPosText(r.text, r.byteLength, r.pos, r.paint)); DRAW(DrawPosTextH, drawPosTextH(r.text, r.byteLength, r.xpos, r.y, r.paint)); DRAW(DrawRRect, drawRRect(r.rrect, r.paint)); DRAW(DrawRect, drawRect(r.rect, r.paint)); DRAW(DrawRegion, drawRegion(r.region, r.paint)); DRAW(DrawText, drawText(r.text, r.byteLength, r.x, r.y, r.paint)); DRAW(DrawTextBlob, drawTextBlob(r.blob.get(), r.x, r.y, r.paint)); DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, &r.matrix, r.paint)); DRAW(DrawTextRSXform, drawTextRSXform(r.text, r.byteLength, r.xforms, r.cull, r.paint)); DRAW(DrawAtlas, drawAtlas(r.atlas.get(), r.xforms, r.texs, r.colors, r.count, r.mode, r.cull, r.paint)); DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors, r.xmode, r.indices, r.indexCount, r.paint)); DRAW(DrawAnnotation, drawAnnotation(r.rect, r.key.c_str(), r.value.get())); #undef DRAW template <> void Draw::draw(const DrawDrawable& r) { SkASSERT(r.index >= 0); SkASSERT(r.index < fDrawableCount); if (fDrawables) { SkASSERT(nullptr == fDrawablePicts); fCanvas->drawDrawable(fDrawables[r.index], r.matrix); } else { fCanvas->drawPicture(fDrawablePicts[r.index], r.matrix, nullptr); } } // This is an SkRecord visitor that fills an SkBBoxHierarchy. // // The interesting part here is how to calculate bounds for ops which don't // have intrinsic bounds. What is the bounds of a Save or a Translate? // // We answer this by thinking about a particular definition of bounds: if I // don't execute this op, pixels in this rectangle might draw incorrectly. So // the bounds of a Save, a Translate, a Restore, etc. are the union of the // bounds of Draw* ops that they might have an effect on. For any given // Save/Restore block, the bounds of the Save, the Restore, and any other // non-drawing ("control") ops inside are exactly the union of the bounds of // the drawing ops inside that block. // // To implement this, we keep a stack of active Save blocks. As we consume ops // inside the Save/Restore block, drawing ops are unioned with the bounds of // the block, and control ops are stashed away for later. When we finish the // block with a Restore, our bounds are complete, and we go back and fill them // in for all the control ops we stashed away. class FillBounds : SkNoncopyable { public: FillBounds(const SkRect& cullRect, const SkRecord& record, SkRect bounds[]) : fNumRecords(record.count()) , fCullRect(cullRect) , fBounds(bounds) { fCTM = SkMatrix::I(); fCurrentClipBounds = fCullRect; } void cleanUp() { // If we have any lingering unpaired Saves, simulate restores to make // sure all ops in those Save blocks have their bounds calculated. while (!fSaveStack.isEmpty()) { this->popSaveBlock(); } // Any control ops not part of any Save/Restore block draw everywhere. while (!fControlIndices.isEmpty()) { this->popControl(fCullRect); } } void setCurrentOp(int currentOp) { fCurrentOp = currentOp; } template <typename T> void operator()(const T& op) { this->updateCTM(op); this->updateClipBounds(op); this->trackBounds(op); } // In this file, SkRect are in local coordinates, Bounds are translated back to identity space. typedef SkRect Bounds; int currentOp() const { return fCurrentOp; } const SkMatrix& ctm() const { return fCTM; } const Bounds& getBounds(int index) const { return fBounds[index]; } // Adjust rect for all paints that may affect its geometry, then map it to identity space. Bounds adjustAndMap(SkRect rect, const SkPaint* paint) const { // Inverted rectangles really confuse our BBHs. rect.sort(); // Adjust the rect for its own paint. if (!AdjustForPaint(paint, &rect)) { // The paint could do anything to our bounds. The only safe answer is the current clip. return fCurrentClipBounds; } // Adjust rect for all the paints from the SaveLayers we're inside. if (!this->adjustForSaveLayerPaints(&rect)) { // Same deal as above. return fCurrentClipBounds; } // Map the rect back to identity space. fCTM.mapRect(&rect); // Nothing can draw outside the current clip. if (!rect.intersect(fCurrentClipBounds)) { return Bounds::MakeEmpty(); } return rect; } private: struct SaveBounds { int controlOps; // Number of control ops in this Save block, including the Save. Bounds bounds; // Bounds of everything in the block. const SkPaint* paint; // Unowned. If set, adjusts the bounds of all ops in this block. SkMatrix ctm; }; // Only Restore, SetMatrix, Concat, and Translate change the CTM. template <typename T> void updateCTM(const T&) {} void updateCTM(const Restore& op) { fCTM = op.matrix; } void updateCTM(const SetMatrix& op) { fCTM = op.matrix; } void updateCTM(const Concat& op) { fCTM.preConcat(op.matrix); } void updateCTM(const Translate& op) { fCTM.preTranslate(op.dx, op.dy); } // Most ops don't change the clip. template <typename T> void updateClipBounds(const T&) {} // Clip{Path,RRect,Rect,Region} obviously change the clip. They all know their bounds already. void updateClipBounds(const ClipPath& op) { this->updateClipBoundsForClipOp(op.devBounds); } void updateClipBounds(const ClipRRect& op) { this->updateClipBoundsForClipOp(op.devBounds); } void updateClipBounds(const ClipRect& op) { this->updateClipBoundsForClipOp(op.devBounds); } void updateClipBounds(const ClipRegion& op) { this->updateClipBoundsForClipOp(op.devBounds); } // The bounds of clip ops need to be adjusted for the paints of saveLayers they're inside. void updateClipBoundsForClipOp(const SkIRect& devBounds) { Bounds clip = SkRect::Make(devBounds); // We don't call adjustAndMap() because as its last step it would intersect the adjusted // clip bounds with the previous clip, exactly what we can't do when the clip grows. if (this->adjustForSaveLayerPaints(&clip)) { fCurrentClipBounds = clip.intersect(fCullRect) ? clip : Bounds::MakeEmpty(); } else { fCurrentClipBounds = fCullRect; } } // Restore holds the devBounds for the clip after the {save,saveLayer}/restore block completes. void updateClipBounds(const Restore& op) { // This is just like the clip ops above, but we need to skip the effects (if any) of our // paired saveLayer (if it is one); it has not yet been popped off the save stack. Our // devBounds reflect the state of the world after the saveLayer/restore block is done, // so they are not affected by the saveLayer's paint. const int kSavesToIgnore = 1; Bounds clip = SkRect::Make(op.devBounds); if (this->adjustForSaveLayerPaints(&clip, kSavesToIgnore)) { fCurrentClipBounds = clip.intersect(fCullRect) ? clip : Bounds::MakeEmpty(); } else { fCurrentClipBounds = fCullRect; } } // We also take advantage of SaveLayer bounds when present to further cut the clip down. void updateClipBounds(const SaveLayer& op) { if (op.bounds) { // adjustAndMap() intersects these layer bounds with the previous clip for us. fCurrentClipBounds = this->adjustAndMap(*op.bounds, op.paint); } } // The bounds of these ops must be calculated when we hit the Restore // from the bounds of the ops in the same Save block. void trackBounds(const Save&) { this->pushSaveBlock(nullptr); } void trackBounds(const SaveLayer& op) { this->pushSaveBlock(op.paint); } void trackBounds(const Restore&) { fBounds[fCurrentOp] = this->popSaveBlock(); } void trackBounds(const SetMatrix&) { this->pushControl(); } void trackBounds(const Concat&) { this->pushControl(); } void trackBounds(const Translate&) { this->pushControl(); } void trackBounds(const TranslateZ&) { this->pushControl(); } void trackBounds(const ClipRect&) { this->pushControl(); } void trackBounds(const ClipRRect&) { this->pushControl(); } void trackBounds(const ClipPath&) { this->pushControl(); } void trackBounds(const ClipRegion&) { this->pushControl(); } // For all other ops, we can calculate and store the bounds directly now. template <typename T> void trackBounds(const T& op) { fBounds[fCurrentOp] = this->bounds(op); this->updateSaveBounds(fBounds[fCurrentOp]); } void pushSaveBlock(const SkPaint* paint) { // Starting a new Save block. Push a new entry to represent that. SaveBounds sb; sb.controlOps = 0; // If the paint affects transparent black, the bound shouldn't be smaller // than the current clip bounds. sb.bounds = PaintMayAffectTransparentBlack(paint) ? fCurrentClipBounds : Bounds::MakeEmpty(); sb.paint = paint; sb.ctm = this->fCTM; fSaveStack.push(sb); this->pushControl(); } static bool PaintMayAffectTransparentBlack(const SkPaint* paint) { if (paint) { // FIXME: this is very conservative if (paint->getImageFilter() || paint->getColorFilter()) { return true; } // Unusual blendmodes require us to process a saved layer // even with operations outisde the clip. // For example, DstIn is used by masking layers. // https://code.google.com/p/skia/issues/detail?id=1291 // https://crbug.com/401593 switch (paint->getBlendMode()) { // For each of the following transfer modes, if the source // alpha is zero (our transparent black), the resulting // blended alpha is not necessarily equal to the original // destination alpha. case SkBlendMode::kClear: case SkBlendMode::kSrc: case SkBlendMode::kSrcIn: case SkBlendMode::kDstIn: case SkBlendMode::kSrcOut: case SkBlendMode::kDstATop: case SkBlendMode::kModulate: return true; break; default: break; } } return false; } Bounds popSaveBlock() { // We're done the Save block. Apply the block's bounds to all control ops inside it. SaveBounds sb; fSaveStack.pop(&sb); while (sb.controlOps --> 0) { this->popControl(sb.bounds); } // This whole Save block may be part another Save block. this->updateSaveBounds(sb.bounds); // If called from a real Restore (not a phony one for balance), it'll need the bounds. return sb.bounds; } void pushControl() { fControlIndices.push(fCurrentOp); if (!fSaveStack.isEmpty()) { fSaveStack.top().controlOps++; } } void popControl(const Bounds& bounds) { fBounds[fControlIndices.top()] = bounds; fControlIndices.pop(); } void updateSaveBounds(const Bounds& bounds) { // If we're in a Save block, expand its bounds to cover these bounds too. if (!fSaveStack.isEmpty()) { fSaveStack.top().bounds.join(bounds); } } // FIXME: this method could use better bounds Bounds bounds(const DrawText&) const { return fCurrentClipBounds; } Bounds bounds(const DrawPaint&) const { return fCurrentClipBounds; } Bounds bounds(const NoOp&) const { return Bounds::MakeEmpty(); } // NoOps don't draw. Bounds bounds(const DrawRect& op) const { return this->adjustAndMap(op.rect, &op.paint); } Bounds bounds(const DrawRegion& op) const { SkRect rect = SkRect::Make(op.region.getBounds()); return this->adjustAndMap(rect, &op.paint); } Bounds bounds(const DrawOval& op) const { return this->adjustAndMap(op.oval, &op.paint); } // Tighter arc bounds? Bounds bounds(const DrawArc& op) const { return this->adjustAndMap(op.oval, &op.paint); } Bounds bounds(const DrawRRect& op) const { return this->adjustAndMap(op.rrect.rect(), &op.paint); } Bounds bounds(const DrawDRRect& op) const { return this->adjustAndMap(op.outer.rect(), &op.paint); } Bounds bounds(const DrawImage& op) const { const SkImage* image = op.image.get(); SkRect rect = SkRect::MakeXYWH(op.left, op.top, image->width(), image->height()); return this->adjustAndMap(rect, op.paint); } Bounds bounds(const DrawImageLattice& op) const { return this->adjustAndMap(op.dst, op.paint); } Bounds bounds(const DrawImageRect& op) const { return this->adjustAndMap(op.dst, op.paint); } Bounds bounds(const DrawImageNine& op) const { return this->adjustAndMap(op.dst, op.paint); } Bounds bounds(const DrawPath& op) const { return op.path.isInverseFillType() ? fCurrentClipBounds : this->adjustAndMap(op.path.getBounds(), &op.paint); } Bounds bounds(const DrawPoints& op) const { SkRect dst; dst.set(op.pts, op.count); // Pad the bounding box a little to make sure hairline points' bounds aren't empty. SkScalar stroke = SkMaxScalar(op.paint.getStrokeWidth(), 0.01f); dst.outset(stroke/2, stroke/2); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawPatch& op) const { SkRect dst; dst.set(op.cubics, SkPatchUtils::kNumCtrlPts); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawVertices& op) const { SkRect dst; dst.set(op.vertices, op.vertexCount); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawAtlas& op) const { if (op.cull) { // TODO: <reed> can we pass nullptr for the paint? Isn't cull already "correct" // for the paint (by the caller)? return this->adjustAndMap(*op.cull, op.paint); } else { return fCurrentClipBounds; } } Bounds bounds(const DrawPicture& op) const { SkRect dst = op.picture->cullRect(); op.matrix.mapRect(&dst); return this->adjustAndMap(dst, op.paint); } Bounds bounds(const DrawShadowedPicture& op) const { SkRect dst = op.picture->cullRect(); op.matrix.mapRect(&dst); return this->adjustAndMap(dst, op.paint); } Bounds bounds(const DrawPosText& op) const { const int N = op.paint.countText(op.text, op.byteLength); if (N == 0) { return Bounds::MakeEmpty(); } SkRect dst; dst.set(op.pos, N); AdjustTextForFontMetrics(&dst, op.paint); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawPosTextH& op) const { const int N = op.paint.countText(op.text, op.byteLength); if (N == 0) { return Bounds::MakeEmpty(); } SkScalar left = op.xpos[0], right = op.xpos[0]; for (int i = 1; i < N; i++) { left = SkMinScalar(left, op.xpos[i]); right = SkMaxScalar(right, op.xpos[i]); } SkRect dst = { left, op.y, right, op.y }; AdjustTextForFontMetrics(&dst, op.paint); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawTextOnPath& op) const { SkRect dst = op.path.getBounds(); // Pad all sides by the maximum padding in any direction we'd normally apply. SkRect pad = { 0, 0, 0, 0}; AdjustTextForFontMetrics(&pad, op.paint); // That maximum padding happens to always be the right pad today. SkASSERT(pad.fLeft == -pad.fRight); SkASSERT(pad.fTop == -pad.fBottom); SkASSERT(pad.fRight > pad.fBottom); dst.outset(pad.fRight, pad.fRight); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawTextRSXform& op) const { if (op.cull) { return this->adjustAndMap(*op.cull, nullptr); } else { return fCurrentClipBounds; } } Bounds bounds(const DrawTextBlob& op) const { SkRect dst = op.blob->bounds(); dst.offset(op.x, op.y); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawDrawable& op) const { return this->adjustAndMap(op.worstCaseBounds, nullptr); } Bounds bounds(const DrawAnnotation& op) const { return this->adjustAndMap(op.rect, nullptr); } static void AdjustTextForFontMetrics(SkRect* rect, const SkPaint& paint) { #ifdef SK_DEBUG SkRect correct = *rect; #endif // crbug.com/373785 ~~> xPad = 4x yPad // crbug.com/424824 ~~> bump yPad from 2x text size to 2.5x const SkScalar yPad = 2.5f * paint.getTextSize(), xPad = 4.0f * yPad; rect->outset(xPad, yPad); #ifdef SK_DEBUG SkPaint::FontMetrics metrics; paint.getFontMetrics(&metrics); correct.fLeft += metrics.fXMin; correct.fTop += metrics.fTop; correct.fRight += metrics.fXMax; correct.fBottom += metrics.fBottom; // See skia:2862 for why we ignore small text sizes. SkASSERTF(paint.getTextSize() < 0.001f || rect->contains(correct), "%f %f %f %f vs. %f %f %f %f\n", -xPad, -yPad, +xPad, +yPad, metrics.fXMin, metrics.fTop, metrics.fXMax, metrics.fBottom); #endif } // Returns true if rect was meaningfully adjusted for the effects of paint, // false if the paint could affect the rect in unknown ways. static bool AdjustForPaint(const SkPaint* paint, SkRect* rect) { if (paint) { if (paint->canComputeFastBounds()) { *rect = paint->computeFastBounds(*rect, rect); return true; } return false; } return true; } bool adjustForSaveLayerPaints(SkRect* rect, int savesToIgnore = 0) const { for (int i = fSaveStack.count() - 1 - savesToIgnore; i >= 0; i--) { SkMatrix inverse; if (!fSaveStack[i].ctm.invert(&inverse)) { return false; } inverse.mapRect(rect); if (!AdjustForPaint(fSaveStack[i].paint, rect)) { return false; } fSaveStack[i].ctm.mapRect(rect); } return true; } const int fNumRecords; // We do not guarantee anything for operations outside of the cull rect const SkRect fCullRect; // Conservative identity-space bounds for each op in the SkRecord. Bounds* fBounds; // We walk fCurrentOp through the SkRecord, as we go using updateCTM() // and updateClipBounds() to maintain the exact CTM (fCTM) and conservative // identity-space bounds of the current clip (fCurrentClipBounds). int fCurrentOp; SkMatrix fCTM; Bounds fCurrentClipBounds; // Used to track the bounds of Save/Restore blocks and the control ops inside them. SkTDArray<SaveBounds> fSaveStack; SkTDArray<int> fControlIndices; }; } // namespace SkRecords
void updateHIN11010(int etPho = 60, int etJet = 30, bool scaleByR=true, bool drawMC=true, int prodDate=20131021) { bool mcOnly=false; int percentBin[5] = {0,10,30,50,100}; TH1D* hxgj[5][10]; //[data kind] [ centrality] TH1D* hxgjpp[20]; TFile *fSum1 = new TFile(Form("histOutputFiles60GeVInclusive/HisOutput_Photonv7_v29_akPu3PF_InclPtRatio_gamma%djet%ddphiSig2749_Isol0_Norm1.root",etPho,etJet)); for ( int icent=0; icent<=3 ; icent++) { hxgj[khimc][icent] = (TH1D*)fSum1->Get(Form("dataSrc%d_reco1_cent%dSubtractedExtrapExtrapNorm",khimc,icent)); hxgj[khidata][icent] = (TH1D*)fSum1->Get(Form("dataSrc%d_reco1_cent%dSubtractedExtrapExtrapNorm",khidata,icent)); } hxgjpp[kppdata] = (TH1D*)fSum1->Get("dataSrc2_reco1_cent0SubtractedExtrapExtrapNorm"); TFile *fSum2 = new TFile(Form("histOutputFiles60GeVInclusive/HisOutput_Photonv7_v29_akPu3PF_InclPtRatio_gamma%djet%ddphiSig2749_Isol0_Norm2.root",etPho,etJet)); TGraphAsymmErrors* mxhimc = (TGraphAsymmErrors*)fSum2->Get("dataSrc0_reco1_x_Summary_0"); TGraphAsymmErrors* mxhidata = (TGraphAsymmErrors*)fSum2->Get("dataSrc1_reco1_x_Summary_0"); // TGraphAsymmErrors* mxppdata = (TGraphAsymmErrors*)fSum2->Get("dataSrc2_reco1_x_Summary_0"); TGraphAsymmErrors* mxppdata; TGraphAsymmErrors* mxppmc = (TGraphAsymmErrors*)fSum2->Get("dataSrc10_reco1_x_Summary_0"); TGraphAsymmErrors* rxhimc = (TGraphAsymmErrors*)fSum2->Get("dataSrc0_reco1_R_Summary_0"); TGraphAsymmErrors* rxhidata = (TGraphAsymmErrors*)fSum2->Get("dataSrc1_reco1_R_Summary_0"); TGraphAsymmErrors* rxppdata = (TGraphAsymmErrors*)fSum2->Get("dataSrc2_reco1_R_Summary_0"); TGraphAsymmErrors* rxppmc = (TGraphAsymmErrors*)fSum2->Get("dataSrc10_reco1_R_Summary_0"); TFile *fSum3 = new TFile(Form("histOutputFiles60GeVInclusive/HisOutput_Photonv7_v29_akPu3PF_InclDeltaPhi_gamma%djet%ddphiSig628_subJ1SS1_Isol0_Norm1.root",etPho,etJet)); TFile *fSum4 = new TFile("histOutputFiles60GeVInclusive/HisSummary_Photonv7_v29_akPu3PF_InclDeltaPhi_gamma60jet30dphiSig628_subJ1SS1_Isol0_Norm1.root"); TGraphAsymmErrors* dphihimc = (TGraphAsymmErrors*)fSum4->Get("dataSrc0_reco1_dphi_Summary"); TGraphAsymmErrors* dphihidata = (TGraphAsymmErrors*)fSum4->Get("dataSrc1_reco1_dphi_Summary"); TGraphAsymmErrors* dphippdata = (TGraphAsymmErrors*)fSum4->Get("dataSrc2_reco1_dphi_Summary"); TGraphAsymmErrors* dphippmc = (TGraphAsymmErrors*)fSum4->Get("dataSrc10_reco1_dphi_Summary"); // new dphihidata points // double sysDphi[4] = {0.032,0.03,0.045,0.077}; //0.109940, 0.046998, 0.034206,0.142664}; double sysDphipp[1] = {sysDphi[3]}; double sysR[4] = {0.045,0.039,0.041,0.037}; //0.017232,0.012847,0.011691,0.012724}; double sysRpp[1] = {sysR[3]}; double sysMx[4] = { 0.053,0.048,0.051,0.032}; double sysMxpp[1] = {0.009}; double corrSysMx = 0.028; TH1D* hdphi[5][5]; //[data kind] [ centrality] TH1D* hdphipp[20]; for ( int icent=0; icent<=3 ; icent++) { hdphi[khimc][icent] = (TH1D*)fSum3->Get(Form("dataSrc%d_reco1_cent%dSubtractedExtrapExtrapNorm",khimc,icent)); hdphi[khidata][icent] = (TH1D*)fSum3->Get(Form("dataSrc%d_reco1_cent%dSubtractedExtrapExtrapNorm",khidata,icent)); } hdphipp[kppdata] = (TH1D*)fSum3->Get("dataSrc2_reco1_cent0SubtractedExtrapExtrapNorm"); // 2013 pp data!!!!!! TFile* pp13 = new TFile(Form("ffFilesPP60GeVInclusive/photonTrackCorr_ppDATA_output_photonPtThr60_to_9999_jetPtThr30_%d.root", prodDate)); // TFile* pp13 = new TFile("ffFilesPP60GeVInclusive/oldSmearing.root"); hdphi[kppdata13][1] = (TH1D*)pp13->Get("jetDphi_icent10010_final"); hxgj[kppdata13][1] = (TH1D*)pp13->Get("xjg_icent10010_final"); hdphi[kppdata13][2] = (TH1D*)pp13->Get("jetDphi_icent11030_final"); hxgj[kppdata13][2] = (TH1D*)pp13->Get("xjg_icent11030_final"); hdphi[kppdata13][3] = (TH1D*)pp13->Get("jetDphi_icent13050_final"); hxgj[kppdata13][3] = (TH1D*)pp13->Get("xjg_icent13050_final"); hdphi[kppdata13][4] = (TH1D*)pp13->Get("jetDphi_icent15099_final"); hxgj[kppdata13][4] = (TH1D*)pp13->Get("xjg_icent15099_final"); hdphi[kppdata13][5] = (TH1D*)pp13->Get("jetDphi_icent7_final"); hxgj[kppdata13][5] = (TH1D*)pp13->Get("xjg_icent7_final"); for ( int icent = 1 ; icent<=5 ; icent++) { hdphi[kppdata13][icent]->Scale(1./hdphi[kppdata13][icent]->Integral()); for ( int i = 1 ; i<=5 ; i++) { hdphi[kppdata13][icent]->SetBinContent(i,-1e4); } // hxgj[kppdata13][icent]->Rebin(10); // Now the bins are already rebined from photonTrackCorr_ppDATA_output_photonPtThr60_to_9999_jetPtThr30_20131021.root hxgj[kppdata13][icent]->Scale(1./hxgj[kppdata13][icent]->Integral("width")); } TH1D* hPtPP2013[10]; hPtPP2013[1] = (TH1D*)pp13->Get("jetPt_icent10010_final"); hPtPP2013[2] = (TH1D*)pp13->Get("jetPt_icent11030_final"); hPtPP2013[3] = (TH1D*)pp13->Get("jetPt_icent13050_final"); hPtPP2013[4] = (TH1D*)pp13->Get("jetPt_icent15099_final"); hPtPP2013[5] = (TH1D*)pp13->Get("jetPt_icent7_final"); TH1D* hRpp2013[10]; hRpp2013[1] = new TH1D("hrpp2013_icent1","",1, 359.1-10, 359.1+10); hRpp2013[2] = new TH1D("hrpp2013_icent2","",1, 235.6-10, 235.6+10); hRpp2013[3] = new TH1D("hrpp2013_icent3","",1, 116.4-10, 116.4+10); hRpp2013[4] = new TH1D("hrpp2013_icent4","",1, 43.6-10, 43.6 +10); hRpp2013[5] = new TH1D("hrpp2013_icent5","",1, -8, 18 ); for ( int icent=1 ; icent<=5; icent++) { double temprPP13err; double temprPP13 = hPtPP2013[icent]->IntegralAndError(1,hPtPP2013[icent]->GetNbinsX(),temprPP13err,"width"); hRpp2013[icent]->SetBinContent(1,temprPP13); hRpp2013[icent]->SetBinError(1,temprPP13err); handsomeTH1(hRpp2013[icent],1); hRpp2013[icent]->SetMarkerStyle(21); } TH1D* hMXpp2013[10]; hMXpp2013[1] = new TH1D("hmxpp2013_icent1","",1, 359.1-10, 359.1+10); hMXpp2013[2] = new TH1D("hmxpp2013_icent2","",1, 235.6-10, 235.6+10); hMXpp2013[3] = new TH1D("hmxpp2013_icent3","",1, 116.4-10, 116.4+10); hMXpp2013[4] = new TH1D("hmxpp2013_icent4","",1, 43.6-10, 43.6 +10); hMXpp2013[5] = new TH1D("hmxpp2013_icent5","",1, -8, 18); for ( int icent=1 ; icent<=5; icent++) { hMXpp2013[icent]->SetBinContent(1,hxgj[kppdata13][icent]->GetMean()); hMXpp2013[icent]->SetBinError(1,hxgj[kppdata13][icent]->GetMeanError()); handsomeTH1(hMXpp2013[icent],1); hMXpp2013[icent]->SetMarkerStyle(21); } TFile* fPPsys = new TFile("ffFilesPP60GeVInclusive/relativeSys_merged_pp60GeV.root"); TH1D* hdphiWidth = (TH1D*)fPPsys->Get("dphiWidth_uncertainty_merged"); TH1D* hDphiPPUnc = new TH1D("hdphippunc","",1,0,1); hDphiPPUnc->SetBinContent(1, hdphiWidth->GetBinContent(1) ); TH1D* ppSysX[4]; ppSysX[0] = (TH1D*)fPPsys->Get("dNdXjg_uncertainty_merged"); ppSysX[1] = (TH1D*)ppSysX[0]->Clone("ppSysx1"); ppSysX[2] = (TH1D*)ppSysX[0]->Clone("ppSysx2"); ppSysX[3] = (TH1D*)ppSysX[0]->Clone("ppSysx3"); TH1D* meanXpp13Sys = (TH1D*)fPPsys->Get("meanXjg_uncertainty_merged"); float ppSysMx60 = meanXpp13Sys->GetBinContent(1); // UPDATED on Oct 22nd TH1D* ppSysMx = new TH1D("ppSysMx","",1,0,1); ppSysMx->SetBinContent(1,ppSysMx60); TH1D* meanRpp13Sys = (TH1D*)fPPsys->Get("meanRjg_uncertainty_merged"); float ppSysR60 = meanRpp13Sys->GetBinContent(1); // UPDATED on Oct 22nd TH1D* ppSysR = new TH1D("ppSysR","",1,0,1); ppSysR->SetBinContent(1,ppSysR60); // xjg distributions TCanvas *c1 = new TCanvas("c1","",1100,330); makeMultiPanelCanvas(c1,4,1,0.0,0.0,0.24,0.15,0.075); c1->cd(0); drawCMSppPbPb(0.1,0.95); //c1->Divide(4,1,0.0,0.0); for ( int icent=0; icent<=3 ; icent++) { c1->cd( 4 - icent); //hxgj[khimc][icent]->SetAxisRange(-.2,2.5,"Y"); hxgj[khimc][icent]->SetAxisRange(0,2.5,"Y"); hxgj[khimc][icent]->SetNdivisions(505); // hxgj[khimc][icent]->SetTitle(";x_{J#gamma} = p^{Jet}_{T}/p^{#gamma}_{T}; #frac{1}{N_{J#gamma}} #frac{dN_{J#gamma}}{dx_{J#gamma}}"); hxgj[khimc][icent]->SetTitle(";x_{J#gamma}; #frac{1}{N_{J#gamma}} #frac{dN_{J#gamma}}{dx_{J#gamma}}"); handsomeTH1(hxgj[khimc][icent]); fixedFontHist(hxgj[khimc][icent],1,1.35); mcStyle2(hxgj[khimc][icent]); handsomeTH1(hxgj[khidata][icent],2); hxgj[khimc][icent]->GetYaxis()->SetTitleOffset(1.5); TH1D * htemp41 = (TH1D*)hxgj[khimc][icent]->Clone(Form("htemp41_%d",icent)); for ( int i=0 ; i<=20 ; i++) { htemp41->SetBinContent(i,0); htemp41->SetBinError(i,0); } if (scaleByR) { htemp41->SetAxisRange(0,2,"Y"); htemp41->SetYTitle("#frac{1}{N_{#gamma}} #frac{dN_{J#gamma}}{dx_{J#gamma}}"); } htemp41->DrawCopy("hist"); if (scaleByR) { hxgj[kppdata13][icent+1]->Scale(hRpp2013[icent+1]->GetBinContent(1)); std::cout <<" Scaled by pp R :" << hRpp2013[icent+1]->GetBinContent(1) << std::endl; double x,y; rxhidata->GetPoint(icent, x,y); hxgj[khidata][icent]->Scale(y); std::cout << " scaled by PbPb R: " << y << std::endl; rxhimc->GetPoint(icent, x,y); hxgj[khimc][icent]->Scale(y); std::cout << " scaled by PbPb R: " << y << std::endl; } if(drawMC) hxgj[khimc][icent]->DrawCopy("hist same"); if ( !mcOnly ) drawXSys(icent,hxgj[khidata][icent]); // if ( icent==3){ } handsomeTH1(hxgj[kppdata13][icent+1]); hxgj[kppdata13][icent+1]->SetMarkerStyle(21); drawSys(hxgj[kppdata13][icent+1],ppSysX[icent],kGreen,3001); hxgj[kppdata13][icent+1]->Draw("same "); if ( !mcOnly ) hxgj[khidata][icent]->Draw("same"); //onSun(0,0,2,0); // if ( icent == 2) { // TLegend *leg0 = new TLegend(0.2796373,0.7545885,0.9742202,0.9937661,NULL,"brNDC"); // easyLeg(leg0,""); // // if ( !mcOnly ) leg0->AddEntry(hxgj[khidata][icent],"PbPb Data","p"); // leg0->AddEntry(hxgj[khimc][icent],"PYTHIA + HYDJET","f"); // leg0->AddEntry(hxgjpp[kppdata],"",""); // leg0->Draw(); // } if ( icent == 3) { TLegend *leg0 = new TLegend(0.2916647,0.7045885,0.9862476,0.9869226,NULL,"brNDC"); easyLeg(leg0); leg0->AddEntry(hxgj[khidata][icent],"PbPb Data","p"); if ( !mcOnly ) leg0->AddEntry(hxgj[kppdata13][icent+1],"Smeared pp reference","p"); // leg0->AddEntry(hxgj[khidata][icent],"",""); if(drawMC) leg0->AddEntry(hxgj[khimc][icent],"PbPb PYTHIA + HYDJET","f"); leg0->Draw(); //drawText("#sqrt{s_{NN}}=2.76 TeV ",0.65,0.74,0,15); } if ( icent == 2) { drawText(Form("p^{#gamma}_{T} > %d GeV/c |#eta^{#gamma}| < 1.44",etPho),0.2,0.85,0,15); drawText(Form("p^{Jet}_{T} > %d GeV/c |#eta^{Jet}| < 1.6",etJet),0.2,0.77,0,15); drawText("#Delta#phi_{J#gamma} > #frac{7}{8}#pi",0.2,0.69,0,15); } if ( icent == 0 ) { // drawText("CMS",0.8,0.9,1); // drawText("pp #int L dt = 231 nb^{-1}",0.4,0.68,1,15); } if ( icent == 3) drawText(Form("%d%% - %d%%",percentBin[icent],percentBin[icent+1]),0.72,0.5,0,15); else drawText(Form("%d%% - %d%%",percentBin[icent],percentBin[icent+1]),0.67,0.5,0,15); /* if ( icent == 3) drawText("(a)",0.275,0.8,1); if ( icent == 2) drawText("(b)",0.05,0.8,1); if ( icent == 1) drawText("(c)",0.05,0.8,1); if ( icent == 0) drawText("(d)",0.05,0.8,1); */ gPad->RedrawAxis(); } c1->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_xjg_distribution.pdf"); //c1->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_xjg_distribution.png"); //c1->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_xjg_distribution.gif"); //c1->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_xjg_distribution.C"); // TCanvas *c1all = new TCanvas("c1all","",500,500); // for ( int icent=0;icent<4;icent++){ // hxgj[khimc][icent]->SetFillStyle(0); // hxgj[khimc][icent]->SetMarkerSize(1.5); // } // hxgj[khimc][0]->SetMarkerStyle(22); // hxgj[khimc][1]->SetMarkerStyle(26); // hxgj[khimc][2]->SetMarkerStyle(23); // hxgj[khimc][3]->SetMarkerStyle(32); // hxgj[khimc][0]->DrawCopy(""); // hxgj[khimc][1]->DrawCopy(" same"); // hxgj[khimc][2]->DrawCopy(" same"); // hxgj[khimc][3]->DrawCopy(" same"); // jumSun(0,0,2,0); // drawText("PYTHIA+HYDJET",0.2,0.80,0,25); // TLegend *legc1all = new TLegend(0.6149194,0.6716102,0.9435484,0.9555085,NULL,"brNDC"); // easyLeg(legc1all,""); // legc1all->AddEntry(hxgj[khimc][3],"50-100%","p"); // legc1all->AddEntry(hxgj[khimc][2],"30-50%","p"); // legc1all->AddEntry(hxgj[khimc][1],"10-30%","p"); // legc1all->AddEntry(hxgj[khimc][0],"0-10%","p"); // legc1all->Draw(); // dphi distributions TCanvas *c1ppDphi = new TCanvas("c1ppDphi","",500,500); TString fitFunc = "(TMath::Pi()/20.0)*exp(-(TMath::Pi()-x)/[0])/([0]*(1-exp(-TMath::Pi()/[0])))"; float fitxmin=3.1415926*2./3; TF1 *fdphiPP[10]; TH1D* hDphiPP2013[10]; hDphiPP2013[1] = new TH1D("hDphiPP2013_icent1","",1, 359.1-10, 359.1+10); hDphiPP2013[2] = new TH1D("hDphiPP2013_icent2","",1, 235.6-10, 235.6+10); hDphiPP2013[3] = new TH1D("hDphiPP2013_icent3","",1, 116.4-10, 116.4+10); hDphiPP2013[4] = new TH1D("hDphiPP2013_icent4","",1, 43.6-10, 43.6 +10); hDphiPP2013[5] = new TH1D("hDphiPP2013_icent5","",1, -8, 18); for ( int icent=1; icent<=5 ; icent++) { fdphiPP[icent] = new TF1(Form("fdphiPP_icent%d",icent),fitFunc.Data(),2.0*TMath::Pi()/3.0,TMath::Pi()); fdphiPP[icent]->SetParName(0,"width"); fdphiPP[icent]->SetParameter("width",0.3); hdphi[kppdata13][icent]->Fit(Form("fdphiPP_icent%d",icent),"0","",fitxmin,3.1415926); fdphiPP[icent]->SetLineWidth(1); fdphiPP[icent]->SetLineStyle(2); fdphiPP[icent]->SetLineColor(1); hdphi[kppdata13][icent]->SetAxisRange(1.00001e-3,1,"Y"); hdphi[kppdata13][icent]->SetStats(0); hdphi[kppdata13][icent]->Draw(""); hdphi[kppdata13][icent]->SetAxisRange(1.00001e-3,1,"Y"); hdphi[kppdata13][icent]->SetStats(0); fdphiPP[icent]->SetLineWidth(2); fdphiPP[icent]->SetLineStyle(7); fdphiPP[icent]->DrawCopy("same"); gPad->SetLogy(); float dphiWidth13 = fdphiPP[icent]->GetParameter(0) ; float dphiWidth13err = fdphiPP[icent]->GetParError(0); hDphiPP2013[icent]->SetBinContent(1,dphiWidth13); hDphiPP2013[icent]->SetBinError( 1,dphiWidth13err); handsomeTH1(hDphiPP2013[icent],1); hDphiPP2013[icent]->SetMarkerStyle(21); } TCanvas *c1dphi = new TCanvas("c1dphi","",1100,330); makeMultiPanelCanvas(c1dphi,4,1,0.0,0.0,0.24,0.18,0.075); c1dphi->cd(0); drawCMSppPbPb(0.1,0.95); for ( int icent=0; icent<=3 ; icent++) { c1dphi->cd( 4 - icent); hdphi[khimc][icent]->SetAxisRange(1.e-3,1,"Y"); // hdphi[khimc][icent]->SetNdivisions(505); hdphi[khimc][icent]->GetXaxis()->SetNdivisions(3,5,0,kFALSE); hdphi[khimc][icent]->SetTitle(";#Delta#phi_{J#gamma};Pair Fraction"); handsomeTH1(hdphi[khimc][icent]); fixedFontHist(hdphi[khimc][icent],1,1.35); mcStyle2(hdphi[khimc][icent]); handsomeTH1(hdphi[khidata][icent],2); TF1 *fdphi = new TF1("fdphi",fitFunc.Data(),2.0*TMath::Pi()/3.0,TMath::Pi()); fdphi->SetParName(0,"width"); fdphi->SetParameter("width",0.3); hdphi[khimc][icent]->Fit("fdphi","0llm","",fitxmin,3.1415926); fdphi->SetLineWidth(1); fdphi->SetLineStyle(2); fdphi->SetLineColor(kBlue); // float dphiWidth = fdphi->GetParameter("width"); // float dphiWidthErr = fdphi->GetParError(0); // std::cout << " dphiWidth,dphiWidthErr = " << dphiWidth <<" "<< dphiWidthErr << std::endl; hdphi[khimc][icent]->SetAxisRange(1.00001e-3,1,"Y"); hdphi[khimc][icent]->SetStats(0); TH1D* hdphitemp = (TH1D*)hdphi[khimc][icent]->Clone(Form("hdphitemp55_%d",icent)); if(!drawMC) { for ( int i=0;i<=30;i++) { hdphitemp->SetBinContent(i,0); hdphitemp->SetBinError(i,0); } } hdphitemp->Draw("hist"); hdphi[khidata][icent]->SetAxisRange(1.00001e-3,1,"Y"); if (!mcOnly) hdphi[khidata][icent]->Draw("same "); hdphi[khidata][icent]->SetStats(0); fdphi->SetLineWidth(2); fdphi->SetLineStyle(7); if ( mcOnly ) fdphi->DrawCopy("same"); gPad->SetLogy(); handsomeTH1(hdphi[kppdata13][icent+1]); hdphi[kppdata13][icent+1]->SetMarkerStyle(21); hdphi[kppdata13][icent+1]->Draw("same"); if ( icent == 3) { TLegend *leg0 = new TLegend(0.32,0.7,0.9,0.89,NULL,"brNDC"); easyLeg(leg0); if ( !mcOnly ) leg0->AddEntry(hdphi[kppdata13][icent+1],"Smeared pp reference","p"); if ( !mcOnly ) leg0->AddEntry(hdphi[khidata][icent],"PbPb Data","p"); if(drawMC) leg0->AddEntry(hdphi[khimc][icent],"PYTHIA + HYDJET","f"); leg0->Draw(); } if (( !mcOnly ) && ( icent == 2)) { //drawText("#sqrt{s_{NN}}=2.76 TeV ",0.4,0.88,0,15); //drawText("#int L dt = 150 #mub^{-1}",0.4,0.75,0,15); } if ( icent == 1) { drawText(Form("p^{#gamma}_{T} > %d GeV/c |#eta^{#gamma}| < 1.44",etPho),0.15,0.8,0,15); drawText(Form("p^{Jet}_{T} > %d GeV/c |#eta^{Jet}| < 1.6",etJet),0.15,0.7,0,15); } if ( icent == 0 ) { // drawText("CMS",0.8,0.9,1); // drawText("pp #int L dt = 231 nb^{-1}",0.4,0.68,1,15); } if ( icent == 3) drawText(Form("%d%% - %d%%",percentBin[icent],percentBin[icent+1]),0.313,0.6,0,15); else drawText(Form("%d%% - %d%%",percentBin[icent],percentBin[icent+1]),0.1,0.6,0,15); if ( icent == 3) drawText("(a)",0.275,0.8,1); if ( icent == 2) drawText("(b)",0.05,0.8,1); if ( icent == 1) drawText("(c)",0.05,0.8,1); if ( icent == 0) drawText("(d)",0.05,0.8,1); double bottomY = 0.0009; double pi = TMath::Pi(); drawPatch(-0.5,bottomY/100,pi+0.5,bottomY); bottomY = 0.0005; drawText("0",0.05,bottomY,0,18,false); drawText("#frac{1}{3}#pi",pi/3-0.05,bottomY,0,18,0); drawText("#frac{2}{3}#pi",2*pi/3-0.05,bottomY,0,18,0); if ( icent==0) drawText("#pi",pi-0.1,bottomY,0,18,0); drawText("#Delta#phi_{J#gamma}",pi/2.-0.1,bottomY-0.0002,0,18,0); } gPad->RedrawAxis(); c1dphi->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_dPhi_dist.pdf"); //c1dphi->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_dPhi_dist.png"); //c1dphi->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_dPhi_dist.gif"); //c1dphi->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_dPhi_dist.C"); ////////////////////////////// summary plots TCanvas *c2 = new TCanvas("c2","",350,350); TH1D* hTemp2 = new TH1D("htemp2",";N_{part};<x_{J#gamma}>",100,-20,400); hTemp2->SetNdivisions(505); handsomeTH1(hTemp2,1); handsomeTGraph(mxhidata,2); mxhidata->SetMarkerStyle(20); handsomeTGraph(mxhimc,1); mxhimc->SetMarkerStyle(24); // handsomeTGraph(mxppdata,1); // mxppdata->SetMarkerStyle(21); handsomeTGraph(mxppmc,1); mxppmc->SetMarkerStyle(25); hTemp2->SetAxisRange(0.6,1.1,"Y"); hTemp2->DrawCopy(); // TH1D* hMXpp2013_2 = new TH1D("hmxpp2013_2","",1,-10,370); // hMXpp2013_2->SetBinContent(1,hMXpp2013->GetBinContent(1)); // if ( !mcOnly ) drawSys(hMXpp2013_2,sysMxpp,kGreen,3001); if ( !mcOnly ) drawSys(mxhidata,sysMx,10); // mxppmc->Draw("p"); // if ( !mcOnly ) mxppdata->Draw("p"); if ( !mcOnly ) { hMXpp2013[5]->SetMarkerStyle(20); for ( int icent = 1 ; icent<=5 ; icent++) { drawSys(hMXpp2013[icent],ppSysMx,kGreen,3001); hMXpp2013[icent]->DrawCopy("p same"); } } if(drawMC) mxhimc->Draw("p same"); if ( !mcOnly ) mxhidata->Draw("p same"); hMXpp2013[5]->SetFillStyle(3001); hMXpp2013[5]->SetFillColor(kGreen); hMXpp2013[5]->SetLineColor(0); hDphiPP2013[2]->SetFillStyle(3001); hDphiPP2013[2]->SetFillColor(kGreen); hDphiPP2013[2]->SetLineColor(0); TH1D *dummyHist = new TH1D("dummyHist","",10,0,1); dummyHist->SetFillStyle(1001); dummyHist->SetMarkerColor(kRed); dummyHist->SetFillColor(90); dummyHist->SetLineColor(0); //// sys bar by energy scale /* TBox *b1 = new TBox(400-20,0.85 - corrSysMx ,400, 0.85 + corrSysMx); b1->SetFillColor(1); b1->SetFillStyle(1001); if ( !mcOnly ) b1->Draw(); TBox *b2 = new TBox(400-20+3,0.85 - corrSysMx+ 0.002 ,400-3, 0.85 + corrSysMx- 0.002); b2->SetFillColor(0); b2->SetFillStyle(1001); if ( !mcOnly ) b2->Draw(); */ // drawText("Common uncertainty due to jet ",0.35,0.25,0,15); // drawText("energy scale & photon purity",0.35,0.2,0,15); // drawText("#sqrt{s_{NN}}=2.76 TeV ",0.5,0.85,0,15); // drawText("#int L dt = 150 #mub^{-1}",0.5,0.72,0,15); // drawText("(a)",0.22,0.87,1); drawText("#Delta#phi_{J#gamma} > #frac{7}{8}#pi",0.7,0.75,0); drawCMSppPbPb(0.1,0.95,12); // drawText("#Delta#phi_{J#gamma} > #frac{7}{8}#pi",0.5,0.38,0); // drawText("CMS",0.78,0.88,1); TLegend *leg4 = new TLegend(0.1630303,0.6054839,0.7590909,0.8931183,NULL,"brNDC"); easyLeg(leg4,""); // if ( !mcOnly ) leg4->AddEntry(mxppdata,"pp Data 231nb^{-1}","p"); if ( !mcOnly ) leg4->AddEntry(dummyHist,"PbPb Data","fp"); if ( !mcOnly ) leg4->AddEntry(hMXpp2013[5],"pp Data","fp"); if ( !mcOnly ) leg4->AddEntry(hDphiPP2013[2],"Smeared pp reference","fp"); if(drawMC) leg4->AddEntry(mxhimc,"PYTHIA + HYDJET","p"); // leg4->AddEntry(mxppmc,"PYTHIA","p"); // leg4->AddEntry(hSysTemp,"Sys. Uncertainty","f"); leg4->Draw(); gPad->RedrawAxis(); c2->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_xjg_npart.pdf"); //c2->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_xjg_npart.png"); //c2->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_xjg_npart.gif"); //c2->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_xjg_npart.C"); ////////////////////////////// rx TCanvas *c3 = new TCanvas("c3","",350,350); TH1D* hTemp3 = new TH1D("htemp2",";N_{part};R_{J#gamma}",100,-20,400); hTemp3->SetNdivisions(505); handsomeTH1(hTemp3,1); handsomeTGraph(rxhidata,2); rxhidata->SetMarkerStyle(20); handsomeTGraph(rxhimc,1); rxhimc->SetMarkerStyle(24); handsomeTGraph(rxppdata,1); rxppdata->SetMarkerStyle(21); handsomeTGraph(rxppmc,1); rxppmc->SetMarkerStyle(25); hTemp3->SetAxisRange(0.41,1.,"Y"); hTemp3->Draw(); // Ratio // DivideTG(rxppdata,rxppmc); // DivideTG(rxhidata,rxhimc); ////////////////////////////////////////////// // TH1D* hdphi2013_2 = new TH1D("hdphi2013_2","",1,-10,370); // hdphi2013_2->SetBinContent(1,hRpp2013->GetBinContent(1)); // if ( !mcOnly ) drawSys(hdphi2013_2,sysRpp,kGreen,3001); if ( !mcOnly ) drawSys(rxhidata,sysR,10); // if ( !mcOnly ) drawSys(rxppdata,sysRpp,10); // jumSun(-10,1,400,1); if(drawMC) rxhimc->Draw("p"); // rxppmc->Draw("p"); // if ( !mcOnly ) rxppdata->Draw("p"); if ( !mcOnly ) { hRpp2013[5]->SetMarkerStyle(20); for ( int icent =1 ; icent<=5 ; icent++) { drawSys(hRpp2013[icent],ppSysR,kGreen,3001); hRpp2013[icent]->Draw("same"); } } if ( !mcOnly ) rxhidata->Draw("p same"); // drawText(Form("p^{#gamma}_{T} > %d GeV/c",etPho),0.6,0.75,0,15); // drawText(Form("p^{Jet}_{T} > %d GeV/c",etJet),0.6,0.67,0,15); // drawText("CMS",0.78,0.88,1); // drawText("(b)",0.22,0.87,1); drawText("#Delta#phi_{J#gamma} > #frac{7}{8}#pi",0.7,0.75,0); drawCMSppPbPb(0.1,0.95,12); leg4->Draw(); gPad->RedrawAxis(); c3->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_r_npart.pdf"); //c3->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_r_npart.png"); //c3->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_r_npart.gif"); //c3->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_r_npart.C"); TCanvas *c4 = new TCanvas("c4","",350,350); TH1D* hTemp4 = new TH1D("htemp2",";N_{part};#sigma(#Delta#phi_{J#gamma})",100,-20,400); hTemp4->SetNdivisions(505); handsomeTH1(hTemp4,1); handsomeTGraph(dphihidata,2); dphihidata->SetMarkerStyle(20); handsomeTGraph(dphihimc,1); dphihimc->SetMarkerStyle(24); handsomeTGraph(dphippdata,1); dphippdata->SetMarkerStyle(21); handsomeTGraph(dphippmc,1); dphippmc->SetMarkerStyle(25); hTemp4->SetAxisRange(0,.5,"Y"); hTemp4->Draw(); // TH1D* h2013_3 = new TH1D("hdphi2013_3","",1,-10,370); // h2013_3->SetBinContent(1,hDphiPP2013->GetBinContent(1)); // if ( !mcOnly ) drawSys(h2013_3,sysDphipp,kGreen,3001); if ( !mcOnly ) drawSys(dphihidata,sysDphi,10); if(drawMC) dphihimc->Draw("p same"); // dphippmc->Draw("p"); // if ( !mcOnly ) dphippdata->Draw("p"); for ( int icent=1 ; icent<=5 ; icent++){ drawSys(hDphiPP2013[icent], hDphiPPUnc, kGreen,3001); } TH1D* hDphiPP2013Temp = new TH1D("hDphiPP2013Temp","",1,380,400); hDphiPP2013Temp->SetBinContent(1,0.27); hDphiPP2013[5]->SetMarkerStyle(20); for ( int icent=1 ; icent<=5 ; icent++){ hDphiPP2013[icent]->Draw("same"); } if ( !mcOnly ) dphihidata->Draw("p"); // TLegend *legDphi = new TLegend(0.32,0.18,0.93,0.7,NULL,"brNDC"); // easyLeg(legDphi,""); // legDphi->SetTextSize(17); // // drawText("|#Delta#phi_{J#gamma}| > #frac{2}{3}#pi",0.5,0.38,0); // // drawText("Fit : #frac{e^{#frac{|#Delta#phi_{J#gamma}|-#pi}{#sigma}}}{#sigma(1-e^{-#pi/#sigma})}",0.5,0.23,0); // legDphi->Draw(); // // drawText("(a)",0.22,0.87,1); // // drawText("CMS",0.78,0.88,1); TH1D* hSysTemp = new TH1D("hSystemp","",1,0,1); hSysTemp->SetFillColor(newYellow); hSysTemp->SetLineColor(newYellow); leg4->Draw(); drawText(Form("p^{#gamma}_{T} > %d GeV/c |#eta^{#gamma}| < 1.44",etPho),0.25,0.3,0,15); drawText(Form("p^{Jet}_{T} > %d GeV/c |#eta^{Jet}| < 1.6",etJet),0.25,0.2,0,15); drawCMSppPbPb(0.1,0.95,12); gPad->RedrawAxis(); c4->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_dphi_npart.pdf"); //c4->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_dphi_npart.png"); //c4->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_dphi_npart.gif"); //c4->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_dphi_npart.C"); // // print numbers // std::cout << " Summary of Points for PbPb " << std::endl; // PrintGraphAndSys(dphihidata,sysDphi); // PrintGraphAndSys(mxhidata,sysMx); // PrintGraphAndSys(rxhidata,sysR); // std::cout << " Summary of Points for PYTHIA + HYDJET " << std::endl; // PrintGraph(dphihimc); // PrintGraph(mxhimc); // PrintGraph(rxhimc); // std::cout << " Summary of Points for pp " << std::endl; // PrintGraphAndSys(dphippdata[5],sysDphipp); // PrintGraphAndSys(mxppdata[5],sysMxpp); // PrintGraphAndSys(rxppdata[5],sysRpp); /* TCanvas *c5 = new TCanvas("c5","",500,500); hxgj[khidata][0]->SetAxisRange(-.2,2.5,"Y"); hxgj[khidata][0]->SetNdivisions(505); fixedFontHist(hxgj[khidata][0],1,1.35); handsomeTH1(hxgj[khidata][0],2); hxgj[khidata][0]->GetYaxis()->SetTitleOffset(1.5); hxgj[khidata][0]->DrawCopy(""); handsomeTH1(hxgj[kppdata13][5],4); hxgj[kppdata13][5]->Draw("same hist"); onSun(0,0,2,0); */ }
void display(void) { int startTime=glutGet(GLUT_ELAPSED_TIME); int counter = 1; glClearDepth(1.0f); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //floor plane glBegin(GL_POLYGON); glColor3f(0.3, 0.73, 0.1); glVertex3f(-75, -0.02, 75); glVertex3f(75, -0.02, 75); glVertex3f(75, -0.02, -75); glVertex3f(-75, -0.02, -75); glEnd(); //draw patches for(int i=0;i<9;i++) { for(int j=0;j<9;j++) { glPushMatrix(); glTranslatef((i-4.5)*10+5, 0, (j-4.5)*10+5); glLoadName(counter); counter++; drawPatch(); glPopMatrix(); } } A0116631House(texSet); /* glPushMatrix(); drawMyHouse(texSet); glTranslatef(10, 0, 0); drawMyHouse(texSet); glTranslatef(10, 0, 0); drawMyHouse(texSet); glTranslatef(10, 0, 0); drawMyHouse(texSet); glTranslatef(10, 0, 0); drawMyHouse(texSet); glPopMatrix(); */ int endTime=glutGet(GLUT_ELAPSED_TIME); cout<<"Frame Rate: "<<(float)1000/(endTime-startTime)<<"\n"; glFlush(); glutSwapBuffers(); }
Patch* MapDraw::draw() { // TODO: Fit this one in too so I don't have to to all the MODEL_SCALE multiplications. // glScalef(MODEL_SCALE, MODEL_SCALE, MODEL_SCALE); int x,y, temp; Patch* bottomLeft = '\0'; Patch* tp = '\0'; // Eventually this call will be made to whatever generic character the // map should be centered on. i.e. the player, or an enemy ant. bottomLeft = getGrid()->getPatch(getCenterX(), getCenterY()); // Shift from the center to the bottomLeft. // shift left a bunch of times or until we hit the left wall. for (temp=0; ((bottomLeft) && (Grid::getLeft(bottomLeft)) && (temp < GRID_SIZE)); temp++) bottomLeft = Grid::getLeft(bottomLeft); int offsetx = 0; // At the bottom, offset... if (temp < GRID_SIZE) offsetx = GRID_SIZE - temp; // shift up a bunch of times or until we hit the top wall. for (temp=0; ((bottomLeft) && (Grid::getDown(bottomLeft)) && (temp < GRID_SIZE)); temp++) bottomLeft = Grid::getDown(bottomLeft); int offsety = 0; // At the bottom, offset... if (temp < GRID_SIZE) offsety = GRID_SIZE - temp; //printf("EXTREME"); tp=bottomLeft; // Setup for drawing. // glBegin(GL_QUADS); for (y=GRID_SIZE*-1 + (offsety); (bottomLeft && (y < (GRID_SIZE+1))); y+=1) { tp=bottomLeft; for (x=GRID_SIZE*-1 + (offsetx); x < (GRID_SIZE+1); x+=1) { if (pickMode) startCheck(); // scale by *MODEL_SCALE then "translate" by adding the smooth scroll factors. // I really have no idea why I was scaling this thing, but I think this is screwing // up tile alignment. // OK, well if x and y get too big I get weird graphical issues with boxes wrapping // around the screen, so lets keep things small for now... drawPatch(x*MODEL_SCALE, y*MODEL_SCALE, tp); if (pickMode) if (endCheck()) { //glEnd(); return tp; } tp=tp->right; } if (bottomLeft) bottomLeft = Grid::getUp(bottomLeft); } // Finished drawing. //glEnd(); return '\0'; }
void photonTemplateProducer(int cutOpt=3, int ppHI = kHI, int isoChoice = kSumIso, int isoCut = -100, bool onlygjEvents=false, float specialSbCut=10, float mcSigShift=0, float sbBkgShift=0) { CutAndBinCollection cab; cab.setCuts(cutOpt); int nPtBin = cab.getNPtBin(); vector<double> ptBinVector = cab.getPtBin(); double ptBin[100]; for ( int i = 0 ; i<=nPtBin ;i++) { ptBin[i] = ptBinVector[i]; } int nCentBin = cab.getNCentBin(); vector<double> centBinVector = cab.getCentBin(); double centBin[100]; for ( int i = 0 ; i<=nCentBin ;i++) { centBin[i] = centBinVector[i]; } TString pphiLabel = ""; if ( ppHI == kPP) pphiLabel = "pp"; TCanvas* c1[5]; TH1D* hData[5][5]; TH1D* hSig[5][5]; TH1D* hBkg[5][5]; // TH1D* hDatapp[5]; // TH1D* hSigpp[5]; // TH1D* hBkgpp[5]; TH1D* hBkgMCsr[5][5]; TH1D* hBkgMCsb[5][5]; TH1D* rawSpectra[5]; TH1D* finSpectra[5]; TH2D* hPurity2D = new TH2D("hPurity2D",";pT(GeV);Centrality bin",nPtBin,ptBin,nCentBin,centBin); int nCent(-1); if ( ppHI == kHI ) nCent = nCentBin; if ( ppHI == kPP ) nCent = 1; for ( int icent = 1 ; icent<=nCent ; icent++) { rawSpectra[icent] = new TH1D(Form("rawSpec_icent%d_%s",icent,getIsoLabel(isoChoice).Data()),"",nPtBin,ptBin); } for (int ipt = 1; ipt <= nPtBin ; ipt++) { c1[ipt] = new TCanvas(Form("c1_ipt%d",ipt),"",700,700); if ( ppHI == kHI ) makeMultiPanelCanvas(c1[ipt],nCent/2,2,0.0,0.0,0.2,0.15,0.02); TCut ptCut = Form("corrPt>%.2f && corrPt<%.2f",(float)ptBin[ipt-1],(float)ptBin[ipt]); for ( int icent = 1 ; icent<=nCent ; icent++) { int lowCent = centBinVector[icent-1]; int highCent = centBinVector[icent]-1; hData[icent][ipt] = new TH1D(Form("hData_cent%d_pt%d",icent,ipt),";shower shape (#sigma_{#eta#eta});Entries per photon candidate;",25,0,0.025); hSig[icent][ipt] = (TH1D*)hData[icent][ipt]->Clone(Form("hSig_cent%d_pt%d",icent,ipt)); hBkg[icent][ipt] = (TH1D*)hData[icent][ipt]->Clone(Form("hBkg_cent%d_pt%d",icent,ipt)); hBkgMCsr[icent][ipt] = (TH1D*)hData[icent][ipt]->Clone(Form("hBkgMCsr_cent%d_pt%d",icent,ipt)); hBkgMCsb[icent][ipt] =(TH1D*)hData[icent][ipt]->Clone(Form("hBkgMCsb_cent%d_pt%d",icent,ipt)); TString fNamedata = fNameHIdata; if ( ppHI == kPP ) fNamedata = fNamePPdata; getTemplate(ppHI, hSig[icent][ipt],"meaningless",isoChoice,isoCut, kSig,lowCent,highCent,ptCut,onlygjEvents,specialSbCut,mcSigShift); getTemplate(ppHI, hData[icent][ipt],fNamedata ,isoChoice,isoCut, kData,lowCent,highCent,ptCut,onlygjEvents,specialSbCut); if ( ppHI == kHI) { getTemplate(ppHI, hBkg[icent][ipt], fNamedata ,isoChoice,isoCut, kSBB,lowCent,highCent,ptCut,onlygjEvents,specialSbCut,sbBkgShift); } if ( ppHI == kPP) getTemplate(ppHI, hBkg[icent][ipt], fNamedata ,isoChoice,isoCut, kSBBpp,lowCent,highCent,ptCut,onlygjEvents,specialSbCut); } for ( int icent = 1 ; icent<=nCent ; icent++) { int lowerCent = centBinVector[icent-1]; int upperCent =centBinVector[icent]-1; c1[ipt]->cd(nCent - icent+1); fitResult fitr = doFit ( hSig[icent][ipt], hBkg[icent][ipt], hData[icent][ipt], 0.005,0.025); if ( icent== nCent) drawPatch(0,0,0.05,0.14,0,1001, "ndc"); cout << " shift = " << mcSigShift << endl; cout << " purity = " << fitr.purity010 << endl; if ( ptBin[ipt]> 200) drawText(Form(" E_{T}^{#gamma} > %d GeV", (int)ptBin[ipt-1]),0.5680963,0.529118); else drawText(Form("%d - %d GeV", (int)ptBin[ipt-1], (int)ptBin[ipt]),0.5680963,0.529118); if ( ppHI == kHI) { drawText(Form("%.0f%% - %.0f%%", float((float)lowerCent*2.5), float((float)(upperCent+1)*2.5)),0.5680963,0.4369118); } else if ( ppHI == kPP) { drawText("7TeV pp",0.5680963,0.4369118); } if ( (icent == nCent) || (icent == 2)) drawText(Form("Purity(#sigma_{#eta#eta} < 0.01) : %.0f%%", (float)fitr.purity010*100),0.5680963,0.3569118,1,15); else drawText(Form("Purity(#sigma_{#eta#eta} < 0.01) : %.0f%%", (float)fitr.purity010*100),0.4980963,0.3569118,1,15); drawText(Form("#pm %.0f%% (stat)", float( 100. * fitr.purity010 * (float)fitr.nSigErr / (float)fitr.nSig ) ),0.6680963,0.2869118,1,15); hPurity2D->SetBinContent(ipt,icent,fitr.purity010); hPurity2D->SetBinError (ipt,icent,fitr.purity010* fitr.nSigErr/fitr.nSig); rawSpectra[icent]->SetBinContent( ipt, fitr.nSig); rawSpectra[icent]->SetBinError( ipt,fitr.nSigErr); TString aa = ""; if (isoChoice == kSumIso) aa = "Sum Iso Method"; if (isoChoice == k3dIso) aa = "3d Cut Method"; if (isoChoice == kFisher) aa = "Fisher Method"; if ( (ppHI == kHI) && ( icent==nCent -1) ) drawText(aa.Data(),0.1980963,0.8569118,1,20); else if ( ppHI == kPP) drawText(aa.Data(),0.1980963,0.8569118,1,20); if ( icent<= 2) drawPatch(0,0,0.05,0.14,0,1001, ndcOpt); // drawPatch(0.9,0.05,1.01,0.14,0,1001,ndcOpt); if ( (ppHI == kPP) && ( mcSigShift != 0 )) drawText(Form("Signal template shifted by %f",mcSigShift),0.1980963,0.7569118,1,15); if ( (ppHI == kHI) && ( mcSigShift != 0 ) && (icent==3)) drawText(Form("Signal template shifted by %f",mcSigShift),0.1980963,0.7569118,1,15); } TString ppLabel =""; if ( ppHI == kPP) ppLabel = "_pp"; TString shiftLabel=""; if ( mcSigShift != 0 ) shiftLabel = Form("_%fSigShifted",(float)mcSigShift); c1[ipt]->SaveAs(Form("fittingPurity%s_%s_pt%d%s.pdf",ppLabel.Data(), getIsoLabel(isoChoice).Data(),ipt,shiftLabel.Data())); } // efficiency plots TCanvas* c2 = new TCanvas("c2","",700,700); //100 + nCent_std*300,400); if ( ppHI == kHI) makeMultiPanelCanvas(c2,nCent/2,2,0.0,0.0,0.2,0.15,0.02); TH1D* heff[7][5]; TH1D* heffGj[5]; TH1D* heffDphi[5]; TH1D* effSingleBin = new TH1D("effSingleBin","",1,60,100000); TGraphAsymmErrors* geff[7][5]; TGraphAsymmErrors* gSingleBin = new TGraphAsymmErrors(); TGraphAsymmErrors* geffGj[5]; TGraphAsymmErrors* geffDphi[5]; for (int icent = 1; icent <=nCent; icent++) { for ( int iid=1 ; iid<=5; iid++) { heff[icent][iid] = new TH1D(Form("heff_icent%d_id%d",icent,iid),";photon E_{T} (GeV);Efficiency",nPtBin, ptBin); if ( isoChoice == kSumIso2) heff[icent][iid]->SetName(Form("heff_icent%d_id%d_isoCut%d",icent,iid,(int)isoCut)); if ( isoChoice == kSumIso3) heff[icent][iid]->SetName(Form("heff_icent%d_id%d_sbIsoCut%d",icent,iid,(int)specialSbCut)); geff[icent][iid] = new TGraphAsymmErrors(); geff[icent][iid]->SetName(Form("geff_%s",heff[icent][iid]->GetName())); } heffGj[icent] = new TH1D(Form("heff_icent%d_Gj", icent),";x_J#gamma;Efficiency",10,0,2); heffDphi[icent] = new TH1D(Form("heff_icent%d_Dphi",icent),";#Delta#phi of pair;Efficiency",9,0.3141592,3.141592); geffGj[icent] = new TGraphAsymmErrors(); geffDphi[icent] = new TGraphAsymmErrors(); } TCut srIsoCut = getIsoCut(isoChoice,isoCut); int nId=4; for (int icent = 1; icent <=nCent ; icent++) { int lowCent = centBinVector[icent-1]; int highCent = centBinVector[icent]-1; TCut centCut = Form("yEvt.hiBin >= %d && yEvt.hiBin<= %d",lowCent,highCent); if ( ppHI == kPP ) centCut = ""; getEff("genMatchedPt",heff[icent][1],geff[icent][1],centCut, "swissCrx<0.90 && seedTime<4"); getEff("genMatchedPt",heff[icent][2],geff[icent][2],centCut, "swissCrx<0.90 && seedTime<4 && hadronicOverEm<0.1"); getEff("genMatchedPt",heff[icent][3],geff[icent][3],centCut, "swissCrx<0.90 && seedTime<4 && hadronicOverEm<0.1" && srIsoCut); getEff("genMatchedPt",heff[icent][4],geff[icent][4],centCut, "swissCrx<0.90 && seedTime<4 && hadronicOverEm<0.1 && sigmaIetaIeta<0.010"&& srIsoCut); effSingleBin->Reset(); getEff("genMatchedPt",effSingleBin, gSingleBin, centCut, "swissCrx<0.90 && seedTime<4 && hadronicOverEm<0.1" && srIsoCut); cout << " here Gj" << endl; getEff("yJet.jtpt/photonEt",heffGj[icent],geffGj[icent], centCut && " genIso<5 && abs(genMomId)<=22 && photonEt>60 && abs(yJet.jteta)<2 && yJet.jtpt>30 && acos(cos(photonPhi-yJet.jtphi))>2.749", "hovere<0.1 && sigmaIetaIeta<0.010 && (cc4+cr4+ct4PtCut20)/0.9<1",true); getEff("acos(cos(photonPhi-yJet.jtphi))",heffDphi[icent],geffDphi[icent],centCut && " genIso<5 && abs(genMomId)<=22 && photonEt>60 && abs(yJet.jteta)<2 && yJet.jtpt>30", "hovere<0.1 && sigmaIetaIeta<0.010 && (cc4+cr4+ct4PtCut20)/0.9<1",true); } for (int icent = 1; icent <=nCent; icent++) { for ( int iid=1 ; iid<=nId ; iid++) { handsomeTH1(heff[icent][iid],ycolor[iid]); handsomeTGraph(geff[icent][iid],ycolor[iid]); } } TH1D* htmp = (TH1D*)heff[1][1]->Clone("htmp"); htmp->Reset(); htmp->SetAxisRange(0,1.3,"Y"); htmp->SetYTitle("Efficiency"); handsomeTH1(htmp); for (int icent = 1; icent <=nCent; icent++) { int lowerCent = centBinVector[icent-1]; int upperCent = centBinVector[icent]-1; if ( ppHI == kHI) c2->cd(nCent - icent + 1); htmp->DrawCopy(); for ( int iid=1 ; iid<=nId ; iid++) { heff[icent][iid]->Draw("p same"); geff[icent][iid]->Draw("p"); } if ( ( icent == nCent ) || ( ppHI == kPP) ) { TLegend* leg1 = new TLegend(0.25,0.20,0.95,0.55,NULL,"brNDC"); easyLeg(leg1,"Photon ID efficiency"); leg1->AddEntry(heff[icent][1],"spike rejection","lp"); leg1->AddEntry(heff[icent][2],"+ H/E < 0.1","lp"); if (isoChoice == kSumIso) leg1->AddEntry(heff[icent][3],"+ SumIso cut","lp"); if (isoChoice == kFisher) leg1->AddEntry(heff[icent][3],"+ Fisher cut","lp"); leg1->AddEntry(heff[icent][4],"+ #sigma_{#eta#eta} <0.010","lp"); leg1->Draw(); } drawText(Form("%.0f%% - %.0f%%", float((float)lowerCent*2.5), float((float)(upperCent+1)*2.5)),0.5680963,0.8369118); if ( icent<=2) drawPatch(0,0,0.05,0.14,0,1001,ndcOpt); // drawPatch(0.9,0.05,1.01,0.14,0,1001,ndcOpt); } c2->SaveAs(Form("photonID_efficiency_%s.pdf",getIsoLabel(isoChoice).Data())); TCanvas* c2b = new TCanvas("c2b","",1000,500); //100 + nCent_std*300,400); c2b->Divide(2,1); c2b->cd(1); TH1D* htmpG = (TH1D*)heffGj[1]->Clone("htmpG"); htmpG->Reset(); htmpG->SetAxisRange(0,1.3,"Y"); htmpG->SetYTitle("Efficiency"); handsomeTH1(htmpG); TLegend* legCent = new TLegend(0.4657258,0.2245763,1,0.4512712,NULL,"brNDC"); easyLeg(legCent,"Centrality"); if (isoChoice == kSumIso) easyLeg(legCent,"SumIso Method"); if (isoChoice == kFisher) easyLeg(legCent,"Fisher Method"); cout<< " heffGj "<< endl << endl<< endl; for (int icent = 1; icent <=nCent; icent++) { handsomeTH1(heffGj[icent],ycolor[icent]); heffGj[icent]->Fit("pol1"); heffGj[icent]->GetFunction("pol1")->SetLineColor(ycolor[icent]); heffGj[icent]->GetFunction("pol1")->SetLineStyle(7); } htmpG->DrawCopy(); for (int icent = 1; icent <=nCent; icent++) { heffGj[icent]->Draw("same"); int lowerCent = centBinVector[icent-1]; int upperCent = centBinVector[icent]-1; legCent->AddEntry(heffGj[icent],Form("%.0f%% - %.0f%%", float((float)lowerCent*2.5), float((float)(upperCent+1)*2.5)),"pl"); } legCent->Draw(); c2b->cd(2); TH1D* htmpDp = new TH1D("htmpDp",";#Delta#phi of pair;Efficiency",10,0,3.14); htmpDp->Reset(); htmpDp->SetAxisRange(0,1.3,"Y"); htmpDp->SetYTitle("Efficiency"); handsomeTH1(htmpDp); cout << " heffDphi " << endl << endl << endl ; for (int icent = 1; icent <=nCent; icent++) { handsomeTH1(heffDphi[icent],ycolor[icent]); heffDphi[icent]->Fit("pol1"); heffDphi[icent]->GetFunction("pol1")->SetLineColor(ycolor[icent]); heffDphi[icent]->GetFunction("pol1")->SetLineStyle(7); } htmpDp->DrawCopy(); for (int icent = 1; icent <=nCent; icent++) { heffDphi[icent]->Draw("same"); } legCent->Draw(); c2b->SaveAs(Form("photonID_efficiency_%s_2.pdf",getIsoLabel(isoChoice).Data())); TCanvas* c3 = new TCanvas("cPurity","",500,500); TH1D* hPurity[10]; for (int icent = 1; icent <=nCent; icent++) { hPurity[icent] = (TH1D*)hPurity2D->ProjectionX(Form("purity1D_icent%d",icent),icent,icent); hPurity[icent]->Fit("pol1"); hPurity[icent]->GetFunction("pol1")->SetLineColor(ycolor[icent]); hPurity[icent]->GetFunction("pol1")->SetLineStyle(7); } TH1D* tempPurity = (TH1D*)hPurity[1]->Clone("purityTemp"); tempPurity->Reset(); handsomeTH1(tempPurity,1); tempPurity->SetXTitle("pT (Gev)"); tempPurity->SetYTitle("Purity"); tempPurity->SetAxisRange(0.45,1.2,"Y"); tempPurity->Draw(); for (int icent = 1; icent <=nCent; icent++) { handsomeTH1(hPurity[icent],ycolor[icent]); hPurity[icent]->Draw("same"); } TLegend* legPurity = new TLegend(0.4657258,0.2245763,1,0.4512712,NULL,"brNDC"); easyLeg(legPurity,"Purity"); if (isoChoice == kSumIso) easyLeg(legPurity,"SumIso Method"); if (isoChoice == kFisher) easyLeg(legPurity,"Fisher Method"); for (int icent = 1; icent <=nCent; icent++){ int lowerCent = centBinVector[icent-1]; int upperCent = centBinVector[icent]-1; legPurity->AddEntry(hPurity[icent],Form("%.0f%% - %.0f%%", float((float)lowerCent*2.5), float((float)(upperCent+1)*2.5)),"pl"); } legPurity->Draw(); if ( !onlygjEvents) drawText("inclusive photon",0.25,0.2); c3->SaveAs(Form("purity_%s.pdf",getIsoLabel(isoChoice).Data())); TCanvas* c4 = new TCanvas("efficiencyCorrection","",1000,500); c4->Divide(2,1); c4->cd(1); for (int icent = 1; icent <=nCent; icent++) { TH1ScaleByWidth(rawSpectra[icent]); // divide by width finSpectra[icent] = (TH1D*)rawSpectra[icent]->Clone(Form("finSpec_icent%d_%s",icent,getIsoLabel(isoChoice).Data())); if ( isoChoice == kSumIso2) finSpectra[icent]->SetName(Form("finSpec_icent%d_%s_isoCut%d",icent,getIsoLabel(isoChoice).Data(),(int)isoCut)); if ( isoChoice == kSumIso3) finSpectra[icent]->SetName(Form("finSpec_icent%d_%s_sbisoCut%d",icent,getIsoLabel(isoChoice).Data(),(int)specialSbCut)); finSpectra[icent]->Divide(heff[icent][3]); handsomeTH1(finSpectra[icent],ycolor[icent]); } // TAA and centrality // TFile outf = TFile(cab.getPurityFileName(),"recreate"); hPurity2D->Write(); for ( int icent=1 ; icent<=nCent ; icent++) { heff[icent][3]->Write(); heff[icent][4]->Write(); finSpectra[icent]->Write(); hPurity[icent]->Write(); for (int ipt = 1; ipt <= nPtBin ; ipt++) { hData[icent][ipt]->Write(); } // hBkgMCRatioFit[icent][1]->Write(); } outf.Close(); }
void GL_Geometry::MakeSphere( float radius, unsigned int quality ) { m_Primitives.clear(); m_Vertices.clear(); m_Normales.clear(); m_TexCoords.clear(); m_Prim_index.clear(); m_Norm_index.clear(); set_treeSearcher.clear(); { unsigned int vertices_size = 12; unsigned int indices_size = 20; int inc = (quality > 0 ? 30 : 0); for (unsigned int i = 0; i < quality; ++i) { indices_size *= 4; vertices_size += inc; inc *= 4; } m_Primitives.resize( indices_size, 0 ); if (vertices_size <= m_Vertices.capacity()) m_Vertices.reserve( vertices_size ); if (vertices_size <= m_Normales.capacity()) m_Normales.reserve( vertices_size ); if (indices_size * 3 <= m_Prim_index.capacity()) m_Prim_index.reserve( indices_size * 3 ); if (indices_size * 3 <= m_Norm_index.capacity()) m_Norm_index.reserve( indices_size * 3 ); } #define D_ICX 0.525731112119133606f #define D_ICZ 0.850650808352039932f static sf::Vector3f idata[12] = { sf::Vector3f(-D_ICX, 0.0f, +D_ICZ), sf::Vector3f(+D_ICX, 0.0f, +D_ICZ), sf::Vector3f(-D_ICX, 0.0f, -D_ICZ), sf::Vector3f(+D_ICX, 0.0f, -D_ICZ), sf::Vector3f(0.0f, +D_ICZ, +D_ICX), sf::Vector3f(0.0f, +D_ICZ, -D_ICX), sf::Vector3f(0.0f, -D_ICZ, +D_ICX), sf::Vector3f(0.0f, -D_ICZ, -D_ICX), sf::Vector3f(+D_ICZ, +D_ICX, 0.0f), sf::Vector3f(-D_ICZ, +D_ICX, 0.0f), sf::Vector3f(+D_ICZ, -D_ICX, 0.0f), sf::Vector3f(-D_ICZ, -D_ICX, 0.0f) }; #undef D_ICX #undef D_ICZ static int index[20][3] = { {0, 4, 1}, { 0, 9, 4}, {9, 5, 4}, { 4, 5, 8}, {4, 8, 1}, { 8, 10, 1}, {8, 3, 10}, { 5, 3, 8}, {5, 2, 3}, { 2, 7, 3}, {7, 10, 3}, { 7, 6, 10}, {7, 11, 6}, {11, 0, 6}, {0, 1, 6}, { 6, 1, 10}, {9, 0, 11}, { 9, 11, 2}, {9, 2, 5}, { 7, 2, 11}, }; t_drawPatch_data::Initialize( m_Vertices, m_Normales, m_TexCoords, m_Prim_index, m_Norm_index, radius ); for (int i = 0; i < 20; i++) { drawPatch( t_drawPatch_data( idata[ index[i][2] ], idata[ index[i][1] ], idata[ index[i][0] ], quality ) ); } // std::cerr << std::endl; // std::cerr << "Sphere stats :" << std::endl; // std::cerr << "m_Vertices :" << m_Vertices.size() << std::endl; // std::cerr << "m_Normales :" << m_Normales.size() << std::endl; // std::cerr << "m_TexCoords :" << m_TexCoords.size() << std::endl; // std::cerr << "m_Prim_index :" << m_Prim_index.size() << std::endl; // std::cerr << "m_Norm_index :" << m_Norm_index.size() << std::endl; // std::cerr << std::endl; // for ( unsigned int i = 0; i < m_Vertices.size(); ++i ) // std::cerr << std::fixed << std::setprecision(2) // << "v (" << std::setw(6) << m_Vertices[i].x // << " / " << std::setw(6) << m_Vertices[i].y // << " / " << std::setw(6) << m_Vertices[i].z << "), " // << "t (" << std::setw(6) << m_TexCoords[i].x // << " / " << std::setw(6) << m_TexCoords[i].y << ")" // << std::endl; // for ( std::vector< sf::Vector3f >::iterator itr = m_Vertices.begin(); // itr != m_Vertices.end(); // ++itr ) // std::cerr << "v :" << itr->x << " / " << itr->y << " / " << itr->z << std::endl; // std::cerr << std::endl; // for ( std::vector< sf::Vector2f >::iterator itr = m_TexCoords.begin(); // itr != m_TexCoords.end(); // ++itr ) // std::cerr << "t :" << itr->x << " / " << itr->y << std::endl; // std::cerr << std::endl; // std::cerr << std::endl; // static std::vector< sf::Vector3f >* s_Vertices; // static std::vector< sf::Vector3f >* s_Normales; // static std::vector< sf::Vector2f >* s_TexCoords; // static std::vector< unsigned int >* s_Indices; // static std::vector< unsigned int >* s_Indices2; // static float s_radius; set_treeSearcher.clear(); Setup(); }
void drawPatch( const t_drawPatch_data& data ) { if (data.s_level > 0) { sf::Vector3f q1, q2, q3; #define D_SET_VERTEX(q, l, r) \ (q).x = 0.5f * ((l).x + (r).x); \ (q).y = 0.5f * ((l).y + (r).y); \ (q).z = 0.5f * ((l).z + (r).z); D_SET_VERTEX(q1, data.s_p1, data.s_p2); D_SET_VERTEX(q2, data.s_p2, data.s_p3); D_SET_VERTEX(q3, data.s_p3, data.s_p1); #undef D_SET_VERTEX #define D_SQ(v) ((v) * (v)) #define D_VEC_LENGTH(v3) (sqrtf( D_SQ( (v3).x ) + D_SQ( (v3).y ) + D_SQ( (v3).z ) )) #define D_NORM(q) \ length = 1.0f / D_VEC_LENGTH(q); \ (q).x *= length; (q).y *= length; (q).z *= length; float length; D_NORM(q1); D_NORM(q2); D_NORM(q3); #undef D_NORM #undef D_VEC_LENGTH #undef D_SQ drawPatch( t_drawPatch_data( data.s_p1, q1, q3, data.s_level - 1 ) ); drawPatch( t_drawPatch_data( q1, data.s_p2, q2, data.s_level - 1 ) ); drawPatch( t_drawPatch_data( q1, q2, q3, data.s_level - 1 ) ); drawPatch( t_drawPatch_data( q3, q2, data.s_p3, data.s_level - 1 ) ); } else { sf::Vector3f* px_array[] = { &data.s_p1, &data.s_p2, &data.s_p3 }; for (int i_point = 0; i_point < 3; ++i_point) { sf::Vector3f& curr_px = *px_array[i_point]; unsigned int i_search = 0; //// std::set< t_index_vertex, t_cmpfunc >::iterator set_itr; t_index_vertex index_vertex(data.s_Normales->size(), &curr_px); set_itr = set_treeSearcher.find( index_vertex ); if (set_itr != set_treeSearcher.end()) i_search = set_itr->s_index; else { i_search = index_vertex.s_index; data.s_Vertices->push_back( curr_px * data.s_radius ); data.s_Normales->push_back( curr_px ); { sf::Vector2f texCoord; { // billboard float theta = 0; float phi = 0; { // sf::Vector3f Center(0, 0, 0); sf::Vector3f Normal(curr_px); // theta = atan2f( Center.y - Normal.y, Center.x - Normal.x ) * 180.0f / 3.14f; theta = atan2f( Normal.y, Normal.x ) * 180.0f / 3.14f; #define D_SQ(v) ((v) * (v)) // #define D_LENGTH(v1, v2) sqrtf( D_SQ((v1).x - (v2).x) + D_SQ((v1).y - (v2).y) ) #define D_LENGTH(v3) sqrtf( D_SQ( (v3).x ) + D_SQ( (v3).y ) ) sf::Vector2f Profile_Pos; // Profile_Pos.x = D_LENGTH( Center, Normal ); // Profile_Pos.y = Center.z - Normal.z; Profile_Pos.x = D_LENGTH( Normal ); Profile_Pos.y = Normal.z; #undef D_SQ phi = atan2f( Profile_Pos.y, Profile_Pos.x ) * 180.0f / 3.14f; } // std::cerr << "phi : " << phi << ", theta : " << theta << std::endl; texCoord.x = (180.0f + theta) / 360.0f; texCoord.y = (90.0f + phi) / 180.0f; // std::cerr << std::fixed << std::setprecision(2) // << "v (" << std::setw(5) << texCoord.x // << " / " << std::setw(5) << texCoord.y // << "), theta (" << std::setw(7) << theta // << "), phi (" << std::setw(7) << phi << ")" << std::endl; } // /billboard // texCoord.x = 0.5f + 0.5f * curr_px.x; // texCoord.y = 0.5f + 0.5f * curr_px.y; // texCoord.x = (1.0f - curr_px.x) * 0.5f; // texCoord.y = (1.0f - curr_px.y) * 0.5f; // std::cerr << "tx : " << texCoord.x << " / " << texCoord.y << std::endl; data.s_TexCoords->push_back( texCoord ); } index_vertex.s_pVertex = &data.s_Normales->back(); set_treeSearcher.insert( index_vertex ); } //// // for (; i_search < data.s_Normales->size(); ++i_search) // if ( (*data.s_Normales)[i_search].x == curr_px.x && // (*data.s_Normales)[i_search].y == curr_px.y && // (*data.s_Normales)[i_search].z == curr_px.z ) // break; // if (i_search == data.s_Normales->size()) // { // data.s_Vertices->push_back( curr_px * data.s_radius ); // data.s_Normales->push_back( curr_px ); // } data.s_Indices->push_back( i_search ); data.s_Indices2->push_back( i_search ); } } }
/* CTextureCanvas::drawTexture * Draws the currently opened composite texture *******************************************************************/ void CTextureCanvas::drawTexture() { // Push matrix glPushMatrix(); // Calculate top-left position of texture (for glScissor, since it ignores the current translation/scale) double left = offset.x + (GetSize().x * 0.5) - (texture->getWidth() * 0.5 * scale); double top = -offset.y + (GetSize().y * 0.5) - (texture->getHeight() * 0.5 * scale); // Translate to middle of the canvas glTranslated(GetSize().x * 0.5, GetSize().y * 0.5, 0); // Zoom double yscale = (tx_arc ? scale * 1.2 : scale); glScaled(scale, yscale, 1); // Draw offset guides if needed drawOffsetLines(); // Apply texture scale double tscalex = 1; double tscaley = 1; if (tex_scale) { tscalex = texture->getScaleX(); if (tscalex == 0) tscalex = 1; tscaley = texture->getScaleY(); if (tscaley == 0) tscaley = 1; glScaled(1.0 / tscalex, 1.0 / tscaley, 1); } // Translate by offsets if needed if (view_type == 0) glTranslated(texture->getWidth() * -0.5, texture->getHeight() * -0.5, 0); // No offsets if (view_type >= 1) glTranslated(-texture->getOffsetX(), -texture->getOffsetY(), 0); // Sprite offsets if (view_type == 2) glTranslated(-160*tscalex, -100*tscaley, 0); // HUD offsets // Draw the texture border //if (gfx_show_border) drawTextureBorder(); // Enable textures glEnable(GL_TEXTURE_2D); // First, draw patches semitransparently (for anything outside the texture) // But only if we are drawing stuff outside the texture area if (draw_outside) { for (uint32_t a = 0; a < texture->nPatches(); a++) drawPatch(a, true); } // Reset colouring OpenGL::setColour(COL_WHITE); // If we're currently dragging, draw a 'basic' preview of the texture using opengl if (dragging) { glEnable(GL_SCISSOR_TEST); glScissor(left, top, texture->getWidth() * scale, texture->getHeight() * scale); for (uint32_t a = 0; a < texture->nPatches(); a++) drawPatch(a); glDisable(GL_SCISSOR_TEST); } // Otherwise, draw the fully generated texture else { // Generate if needed if (!tex_preview.isLoaded()) { // Determine image type SIType type = PALMASK; if (blend_rgba) type = RGBA; // CTexture -> temp Image -> GLTexture SImage temp(type); texture->toImage(temp, parent, &palette, blend_rgba); tex_preview.loadImage(&temp, &palette); } // Draw it tex_preview.draw2d(); } // Disable textures glDisable(GL_TEXTURE_2D); // Now loop through selected patches and draw selection outlines OpenGL::setColour(70, 210, 220, 255, BLEND_NORMAL); glEnable(GL_LINE_SMOOTH); glLineWidth(1.5f); for (size_t a = 0; a < selected_patches.size(); a++) { // Skip if not selected if (!selected_patches[a]) continue; // Get patch CTPatch* patch = texture->getPatch(a); CTPatchEx* epatch = (CTPatchEx*)patch; // Check for rotation if (texture->isExtended() && (epatch->getRotation() == 90 || epatch->getRotation() == -90)) { // Draw outline, width/height swapped glBegin(GL_LINE_LOOP); glVertex2i(patch->xOffset(), patch->yOffset()); glVertex2i(patch->xOffset(), patch->yOffset() + (int)patch_textures[a]->getWidth()); glVertex2i(patch->xOffset() + (int)patch_textures[a]->getHeight(), patch->yOffset() + (int)patch_textures[a]->getWidth()); glVertex2i(patch->xOffset() + (int)patch_textures[a]->getHeight(), patch->yOffset()); glEnd(); } else { // Draw outline glBegin(GL_LINE_LOOP); glVertex2i(patch->xOffset(), patch->yOffset()); glVertex2i(patch->xOffset(), patch->yOffset() + (int)patch_textures[a]->getHeight()); glVertex2i(patch->xOffset() + (int)patch_textures[a]->getWidth(), patch->yOffset() + (int)patch_textures[a]->getHeight()); glVertex2i(patch->xOffset() + (int)patch_textures[a]->getWidth(), patch->yOffset()); glEnd(); } } // Finally, draw a hilight outline if anything is hilighted if (hilight_patch >= 0) { // Set colour OpenGL::setColour(255, 255, 255, 150, BLEND_ADDITIVE); // Get patch CTPatch* patch = texture->getPatch(hilight_patch); CTPatchEx* epatch = (CTPatchEx*)patch; GLTexture* patch_texture = patch_textures[hilight_patch]; // Check for rotation if (texture->isExtended() && (epatch->getRotation() == 90 || epatch->getRotation() == -90)) { // Draw outline, width/height swapped glBegin(GL_LINE_LOOP); glVertex2i(patch->xOffset(), patch->yOffset()); glVertex2i(patch->xOffset(), patch->yOffset() + (int)patch_texture->getWidth()); glVertex2i(patch->xOffset() + (int)patch_texture->getHeight(), patch->yOffset() + (int)patch_texture->getWidth()); glVertex2i(patch->xOffset() + (int)patch_texture->getHeight(), patch->yOffset()); glEnd(); } else { // Draw outline glBegin(GL_LINE_LOOP); glVertex2i(patch->xOffset(), patch->yOffset()); glVertex2i(patch->xOffset(), patch->yOffset() + (int)patch_texture->getHeight()); glVertex2i(patch->xOffset() + (int)patch_texture->getWidth(), patch->yOffset() + (int)patch_texture->getHeight()); glVertex2i(patch->xOffset() + (int)patch_texture->getWidth(), patch->yOffset()); glEnd(); } } glDisable(GL_LINE_SMOOTH); glLineWidth(1.0f); // Pop matrix glPopMatrix(); }
// ###################################################################### // get gist histogram to visualize the data Image<float> RawGistEstimatorGen::getGistImage(int sqSize, float minO, float maxO, float minC, float maxC, float minI, float maxI) { // square size int s = sqSize; Image<float> img(NUM_GIST_COL * s, NUM_GIST_FEAT * s, ZEROS); float range; // setup range for orientation channel if necessary if(maxO == minO) { minO = itsGistVector.getVal(0); maxO = itsGistVector.getVal(0); for(int i = 0; i < 16; i++) for(int j = 0; j < NUM_GIST_FEAT; j++) { float val = itsGistVector.getVal(i*NUM_GIST_FEAT+j); if(val < minO) minO = val; else if(val > maxO) maxO = val; } LDEBUG("Orientation Channel Min: %f, max: %f", minO, maxO); } range = maxO - minO; // orientation channel for(int a = 0; a < 4; a++) for(int b = 0; b < 4; b++) for(int j = 0; j < NUM_GIST_FEAT; j++) { int i = b*4 + a; int ii = a*4 + b; float val = itsGistVector.getVal(ii*NUM_GIST_FEAT+j); drawPatch(img, Point2D<int>(i*s+s/2,j*s+s/2),s/2,(val-minO)/range); } // setup range for color channel if necessary if(maxC == minC) { minC = itsGistVector.getVal(16*NUM_GIST_FEAT); maxC = itsGistVector.getVal(16*NUM_GIST_FEAT); for(int i = 16; i < 28; i++) for(int j = 0; j < NUM_GIST_FEAT; j++) { float val = itsGistVector.getVal(i*NUM_GIST_FEAT+j); if(val < minC) minC = val; else if(val > maxC) maxC = val; } LDEBUG("Color Channel Min: %f, max: %f", minC, maxC); } range = maxC - minC; // color channel for(int i = 16; i < 28; i++) for(int j = 0; j < NUM_GIST_FEAT; j++) { float val = itsGistVector.getVal(i*NUM_GIST_FEAT+j); drawPatch(img, Point2D<int>(i*s+s/2,j*s+s/2),s/2,(val-minC)/range); } // setup range for intensity channel if necessary if(maxI == minI) { minI = itsGistVector.getVal(28*NUM_GIST_FEAT); maxI = itsGistVector.getVal(28*NUM_GIST_FEAT); for(int i = 28; i < 34; i++) for(int j = 0; j < NUM_GIST_FEAT; j++) { float val = itsGistVector.getVal(i*NUM_GIST_FEAT+j); if(val < minI) minI = val; else if(val > maxI) maxI = val; } LDEBUG("Intensity Channel Min: %f, max: %f", minI, maxI); } range = maxI - minI; // intensity channel for(int i = 28; i < NUM_GIST_COL; i++) for(int j = 0; j < NUM_GIST_FEAT; j++) { float val = itsGistVector.getVal(i*NUM_GIST_FEAT+j); drawPatch(img, Point2D<int>(i*s+s/2,j*s+s/2),s/2,(val-minI)/range); } // draw the delineation // spatially float max = 1.0f; drawLine(img, Point2D<int>(0, 1*s), Point2D<int>(NUM_GIST_COL*s, 1*s), max, 1); drawLine(img, Point2D<int>(0, 5*s), Point2D<int>(NUM_GIST_COL*s, 5*s), max, 1); drawLine(img, Point2D<int>(0, 9*s), Point2D<int>(NUM_GIST_COL*s, 9*s), max/2, 1); drawLine(img, Point2D<int>(0, 13*s), Point2D<int>(NUM_GIST_COL*s, 13*s), max/2, 1); drawLine(img, Point2D<int>(0, 17*s), Point2D<int>(NUM_GIST_COL*s, 17*s), max/2, 1); // channelwise drawLine(img, Point2D<int>( 4*s, 0), Point2D<int>( 4*s, NUM_GIST_FEAT*s), max, 1); drawLine(img, Point2D<int>( 8*s, 0), Point2D<int>( 8*s, NUM_GIST_FEAT*s), max, 1); drawLine(img, Point2D<int>(12*s, 0), Point2D<int>(12*s, NUM_GIST_FEAT*s), max, 1); drawLine(img, Point2D<int>(16*s, 0), Point2D<int>(16*s, NUM_GIST_FEAT*s), max, 1); drawLine(img, Point2D<int>(22*s, 0), Point2D<int>(22*s, NUM_GIST_FEAT*s), max, 1); drawLine(img, Point2D<int>(28*s, 0), Point2D<int>(28*s, NUM_GIST_FEAT*s), max, 1); return img; }
namespace SkRecords { // FIXME: SkBitmaps are stateful, so we need to copy them to play back in multiple threads. static SkBitmap shallow_copy(const SkBitmap& bitmap) { return bitmap; } // NoOps draw nothing. template <> void Draw::draw(const NoOp&) {} #define DRAW(T, call) template <> void Draw::draw(const T& r) { fCanvas->call; } DRAW(Restore, restore()); DRAW(Save, save()); DRAW(SaveLayer, saveLayer(r.bounds, r.paint, r.flags)); DRAW(PopCull, popCull()); DRAW(PushCull, pushCull(r.rect)); DRAW(Clear, clear(r.color)); DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix))); DRAW(ClipPath, clipPath(r.path, r.op, r.doAA)); DRAW(ClipRRect, clipRRect(r.rrect, r.op, r.doAA)); DRAW(ClipRect, clipRect(r.rect, r.op, r.doAA)); DRAW(ClipRegion, clipRegion(r.region, r.op)); DRAW(BeginCommentGroup, beginCommentGroup(r.description)); DRAW(AddComment, addComment(r.key, r.value)); DRAW(EndCommentGroup, endCommentGroup()); DRAW(DrawBitmap, drawBitmap(shallow_copy(r.bitmap), r.left, r.top, r.paint)); DRAW(DrawBitmapMatrix, drawBitmapMatrix(shallow_copy(r.bitmap), r.matrix, r.paint)); DRAW(DrawBitmapNine, drawBitmapNine(shallow_copy(r.bitmap), r.center, r.dst, r.paint)); DRAW(DrawBitmapRectToRect, drawBitmapRectToRect(shallow_copy(r.bitmap), r.src, r.dst, r.paint, r.flags)); DRAW(DrawDRRect, drawDRRect(r.outer, r.inner, r.paint)); DRAW(DrawImage, drawImage(r.image, r.left, r.top, r.paint)); DRAW(DrawImageRect, drawImageRect(r.image, r.src, r.dst, r.paint)); DRAW(DrawOval, drawOval(r.oval, r.paint)); DRAW(DrawPaint, drawPaint(r.paint)); DRAW(DrawPath, drawPath(r.path, r.paint)); DRAW(DrawPatch, drawPatch(r.cubics, r.colors, r.texCoords, r.xmode, r.paint)); DRAW(DrawPicture, drawPicture(r.picture, r.matrix, r.paint)); DRAW(DrawPoints, drawPoints(r.mode, r.count, r.pts, r.paint)); DRAW(DrawPosText, drawPosText(r.text, r.byteLength, r.pos, r.paint)); DRAW(DrawPosTextH, drawPosTextH(r.text, r.byteLength, r.xpos, r.y, r.paint)); DRAW(DrawRRect, drawRRect(r.rrect, r.paint)); DRAW(DrawRect, drawRect(r.rect, r.paint)); DRAW(DrawSprite, drawSprite(shallow_copy(r.bitmap), r.left, r.top, r.paint)); DRAW(DrawText, drawText(r.text, r.byteLength, r.x, r.y, r.paint)); DRAW(DrawTextBlob, drawTextBlob(r.blob, r.x, r.y, r.paint)); DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, r.matrix, r.paint)); DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors, r.xmode.get(), r.indices, r.indexCount, r.paint)); DRAW(DrawData, drawData(r.data, r.length)); #undef DRAW // This is an SkRecord visitor that fills an SkBBoxHierarchy. // // The interesting part here is how to calculate bounds for ops which don't // have intrinsic bounds. What is the bounds of a Save or a Translate? // // We answer this by thinking about a particular definition of bounds: if I // don't execute this op, pixels in this rectangle might draw incorrectly. So // the bounds of a Save, a Translate, a Restore, etc. are the union of the // bounds of Draw* ops that they might have an effect on. For any given // Save/Restore block, the bounds of the Save, the Restore, and any other // non-drawing ("control") ops inside are exactly the union of the bounds of // the drawing ops inside that block. // // To implement this, we keep a stack of active Save blocks. As we consume ops // inside the Save/Restore block, drawing ops are unioned with the bounds of // the block, and control ops are stashed away for later. When we finish the // block with a Restore, our bounds are complete, and we go back and fill them // in for all the control ops we stashed away. class FillBounds : SkNoncopyable { public: FillBounds(const SkRect& cullRect, const SkRecord& record, SkBBoxHierarchy* bbh) : fCullRect(cullRect) , fBounds(record.count()) { // Calculate bounds for all ops. This won't go quite in order, so we'll need // to store the bounds separately then feed them in to the BBH later in order. fCTM = &SkMatrix::I(); fCurrentClipBounds = fCullRect; for (fCurrentOp = 0; fCurrentOp < record.count(); fCurrentOp++) { record.visit<void>(fCurrentOp, *this); } // If we have any lingering unpaired Saves, simulate restores to make // sure all ops in those Save blocks have their bounds calculated. while (!fSaveStack.isEmpty()) { this->popSaveBlock(); } // Any control ops not part of any Save/Restore block draw everywhere. while (!fControlIndices.isEmpty()) { this->popControl(fCullRect); } // Finally feed all stored bounds into the BBH. They'll be returned in this order. SkASSERT(bbh); bbh->insert(&fBounds, record.count()); } template <typename T> void operator()(const T& op) { this->updateCTM(op); this->updateClipBounds(op); this->trackBounds(op); } private: // In this file, SkRect are in local coordinates, Bounds are translated back to identity space. typedef SkRect Bounds; struct SaveBounds { int controlOps; // Number of control ops in this Save block, including the Save. Bounds bounds; // Bounds of everything in the block. const SkPaint* paint; // Unowned. If set, adjusts the bounds of all ops in this block. }; // Only Restore and SetMatrix change the CTM. template <typename T> void updateCTM(const T&) {} void updateCTM(const Restore& op) { fCTM = &op.matrix; } void updateCTM(const SetMatrix& op) { fCTM = &op.matrix; } // Most ops don't change the clip. template <typename T> void updateClipBounds(const T&) {} // Clip{Path,RRect,Rect,Region} obviously change the clip. They all know their bounds already. void updateClipBounds(const ClipPath& op) { this->updateClipBoundsForClipOp(op.devBounds); } void updateClipBounds(const ClipRRect& op) { this->updateClipBoundsForClipOp(op.devBounds); } void updateClipBounds(const ClipRect& op) { this->updateClipBoundsForClipOp(op.devBounds); } void updateClipBounds(const ClipRegion& op) { this->updateClipBoundsForClipOp(op.devBounds); } // The bounds of clip ops need to be adjusted for the paints of saveLayers they're inside. void updateClipBoundsForClipOp(const SkIRect& devBounds) { Bounds clip = SkRect::Make(devBounds); // We don't call adjustAndMap() because as its last step it would intersect the adjusted // clip bounds with the previous clip, exactly what we can't do when the clip grows. fCurrentClipBounds = this->adjustForSaveLayerPaints(&clip) ? clip : fCullRect; } // Restore holds the devBounds for the clip after the {save,saveLayer}/restore block completes. void updateClipBounds(const Restore& op) { // This is just like the clip ops above, but we need to skip the effects (if any) of our // paired saveLayer (if it is one); it has not yet been popped off the save stack. Our // devBounds reflect the state of the world after the saveLayer/restore block is done, // so they are not affected by the saveLayer's paint. const int kSavesToIgnore = 1; Bounds clip = SkRect::Make(op.devBounds); fCurrentClipBounds = this->adjustForSaveLayerPaints(&clip, kSavesToIgnore) ? clip : fCullRect; } // We also take advantage of SaveLayer bounds when present to further cut the clip down. void updateClipBounds(const SaveLayer& op) { if (op.bounds) { // adjustAndMap() intersects these layer bounds with the previous clip for us. fCurrentClipBounds = this->adjustAndMap(*op.bounds, op.paint); } } // The bounds of these ops must be calculated when we hit the Restore // from the bounds of the ops in the same Save block. void trackBounds(const Save&) { this->pushSaveBlock(NULL); } void trackBounds(const SaveLayer& op) { this->pushSaveBlock(op.paint); } void trackBounds(const Restore&) { fBounds[fCurrentOp] = this->popSaveBlock(); } void trackBounds(const SetMatrix&) { this->pushControl(); } void trackBounds(const ClipRect&) { this->pushControl(); } void trackBounds(const ClipRRect&) { this->pushControl(); } void trackBounds(const ClipPath&) { this->pushControl(); } void trackBounds(const ClipRegion&) { this->pushControl(); } void trackBounds(const PushCull&) { this->pushControl(); } void trackBounds(const PopCull&) { this->pushControl(); } void trackBounds(const BeginCommentGroup&) { this->pushControl(); } void trackBounds(const AddComment&) { this->pushControl(); } void trackBounds(const EndCommentGroup&) { this->pushControl(); } void trackBounds(const DrawData&) { this->pushControl(); } // For all other ops, we can calculate and store the bounds directly now. template <typename T> void trackBounds(const T& op) { fBounds[fCurrentOp] = this->bounds(op); this->updateSaveBounds(fBounds[fCurrentOp]); } void pushSaveBlock(const SkPaint* paint) { // Starting a new Save block. Push a new entry to represent that. SaveBounds sb; sb.controlOps = 0; // If the paint affects transparent black, the bound shouldn't be smaller // than the current clip bounds. sb.bounds = PaintMayAffectTransparentBlack(paint) ? fCurrentClipBounds : Bounds::MakeEmpty(); sb.paint = paint; fSaveStack.push(sb); this->pushControl(); } static bool PaintMayAffectTransparentBlack(const SkPaint* paint) { if (paint) { // FIXME: this is very conservative if (paint->getImageFilter() || paint->getColorFilter()) { return true; } // Unusual Xfermodes require us to process a saved layer // even with operations outisde the clip. // For example, DstIn is used by masking layers. // https://code.google.com/p/skia/issues/detail?id=1291 // https://crbug.com/401593 SkXfermode* xfermode = paint->getXfermode(); SkXfermode::Mode mode; // SrcOver is ok, and is also the common case with a NULL xfermode. // So we should make that the fast path and bypass the mode extraction // and test. if (xfermode && xfermode->asMode(&mode)) { switch (mode) { // For each of the following transfer modes, if the source // alpha is zero (our transparent black), the resulting // blended alpha is not necessarily equal to the original // destination alpha. case SkXfermode::kClear_Mode: case SkXfermode::kSrc_Mode: case SkXfermode::kSrcIn_Mode: case SkXfermode::kDstIn_Mode: case SkXfermode::kSrcOut_Mode: case SkXfermode::kDstATop_Mode: case SkXfermode::kModulate_Mode: return true; break; default: break; } } } return false; } Bounds popSaveBlock() { // We're done the Save block. Apply the block's bounds to all control ops inside it. SaveBounds sb; fSaveStack.pop(&sb); while (sb.controlOps --> 0) { this->popControl(sb.bounds); } // This whole Save block may be part another Save block. this->updateSaveBounds(sb.bounds); // If called from a real Restore (not a phony one for balance), it'll need the bounds. return sb.bounds; } void pushControl() { fControlIndices.push(fCurrentOp); if (!fSaveStack.isEmpty()) { fSaveStack.top().controlOps++; } } void popControl(const Bounds& bounds) { fBounds[fControlIndices.top()] = bounds; fControlIndices.pop(); } void updateSaveBounds(const Bounds& bounds) { // If we're in a Save block, expand its bounds to cover these bounds too. if (!fSaveStack.isEmpty()) { fSaveStack.top().bounds.join(bounds); } } // FIXME: this method could use better bounds Bounds bounds(const DrawText&) const { return fCurrentClipBounds; } Bounds bounds(const Clear&) const { return fCullRect; } // Ignores the clip. Bounds bounds(const DrawPaint&) const { return fCurrentClipBounds; } Bounds bounds(const NoOp&) const { return Bounds::MakeEmpty(); } // NoOps don't draw. Bounds bounds(const DrawSprite& op) const { const SkBitmap& bm = op.bitmap; return Bounds::MakeXYWH(op.left, op.top, bm.width(), bm.height()); // Ignores the matrix. } Bounds bounds(const DrawRect& op) const { return this->adjustAndMap(op.rect, &op.paint); } Bounds bounds(const DrawOval& op) const { return this->adjustAndMap(op.oval, &op.paint); } Bounds bounds(const DrawRRect& op) const { return this->adjustAndMap(op.rrect.rect(), &op.paint); } Bounds bounds(const DrawDRRect& op) const { return this->adjustAndMap(op.outer.rect(), &op.paint); } Bounds bounds(const DrawImage& op) const { const SkImage* image = op.image; SkRect rect = SkRect::MakeXYWH(op.left, op.top, image->width(), image->height()); return this->adjustAndMap(rect, op.paint); } Bounds bounds(const DrawImageRect& op) const { return this->adjustAndMap(op.dst, op.paint); } Bounds bounds(const DrawBitmapRectToRect& op) const { return this->adjustAndMap(op.dst, op.paint); } Bounds bounds(const DrawBitmapNine& op) const { return this->adjustAndMap(op.dst, op.paint); } Bounds bounds(const DrawBitmap& op) const { const SkBitmap& bm = op.bitmap; return this->adjustAndMap(SkRect::MakeXYWH(op.left, op.top, bm.width(), bm.height()), op.paint); } Bounds bounds(const DrawBitmapMatrix& op) const { const SkBitmap& bm = op.bitmap; SkRect dst = SkRect::MakeWH(bm.width(), bm.height()); op.matrix.mapRect(&dst); return this->adjustAndMap(dst, op.paint); } Bounds bounds(const DrawPath& op) const { return op.path.isInverseFillType() ? fCurrentClipBounds : this->adjustAndMap(op.path.getBounds(), &op.paint); } Bounds bounds(const DrawPoints& op) const { SkRect dst; dst.set(op.pts, op.count); // Pad the bounding box a little to make sure hairline points' bounds aren't empty. SkScalar stroke = SkMaxScalar(op.paint.getStrokeWidth(), 0.01f); dst.outset(stroke/2, stroke/2); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawPatch& op) const { SkRect dst; dst.set(op.cubics, SkPatchUtils::kNumCtrlPts); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawVertices& op) const { SkRect dst; dst.set(op.vertices, op.vertexCount); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawPicture& op) const { SkRect dst = op.picture->cullRect(); if (op.matrix) { op.matrix->mapRect(&dst); } return this->adjustAndMap(dst, op.paint); } Bounds bounds(const DrawPosText& op) const { const int N = op.paint.countText(op.text, op.byteLength); if (N == 0) { return Bounds::MakeEmpty(); } SkRect dst; dst.set(op.pos, N); AdjustTextForFontMetrics(&dst, op.paint); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawPosTextH& op) const { const int N = op.paint.countText(op.text, op.byteLength); if (N == 0) { return Bounds::MakeEmpty(); } SkScalar left = op.xpos[0], right = op.xpos[0]; for (int i = 1; i < N; i++) { left = SkMinScalar(left, op.xpos[i]); right = SkMaxScalar(right, op.xpos[i]); } SkRect dst = { left, op.y, right, op.y }; AdjustTextForFontMetrics(&dst, op.paint); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawTextOnPath& op) const { SkRect dst = op.path.getBounds(); // Pad all sides by the maximum padding in any direction we'd normally apply. SkRect pad = { 0, 0, 0, 0}; AdjustTextForFontMetrics(&pad, op.paint); // That maximum padding happens to always be the right pad today. SkASSERT(pad.fLeft == -pad.fRight); SkASSERT(pad.fTop == -pad.fBottom); SkASSERT(pad.fRight > pad.fBottom); dst.outset(pad.fRight, pad.fRight); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawTextBlob& op) const { SkRect dst = op.blob->bounds(); dst.offset(op.x, op.y); return this->adjustAndMap(dst, &op.paint); } static void AdjustTextForFontMetrics(SkRect* rect, const SkPaint& paint) { #ifdef SK_DEBUG SkRect correct = *rect; #endif // crbug.com/373785 ~~> xPad = 4x yPad // crbug.com/424824 ~~> bump yPad from 2x text size to 2.5x const SkScalar yPad = 2.5f * paint.getTextSize(), xPad = 4.0f * yPad; rect->outset(xPad, yPad); #ifdef SK_DEBUG SkPaint::FontMetrics metrics; paint.getFontMetrics(&metrics); correct.fLeft += metrics.fXMin; correct.fTop += metrics.fTop; correct.fRight += metrics.fXMax; correct.fBottom += metrics.fBottom; // See skia:2862 for why we ignore small text sizes. SkASSERTF(paint.getTextSize() < 0.001f || rect->contains(correct), "%f %f %f %f vs. %f %f %f %f\n", -xPad, -yPad, +xPad, +yPad, metrics.fXMin, metrics.fTop, metrics.fXMax, metrics.fBottom); #endif } // Returns true if rect was meaningfully adjusted for the effects of paint, // false if the paint could affect the rect in unknown ways. static bool AdjustForPaint(const SkPaint* paint, SkRect* rect) { if (paint) { if (paint->canComputeFastBounds()) { *rect = paint->computeFastBounds(*rect, rect); return true; } return false; } return true; } bool adjustForSaveLayerPaints(SkRect* rect, int savesToIgnore = 0) const { for (int i = fSaveStack.count() - 1 - savesToIgnore; i >= 0; i--) { if (!AdjustForPaint(fSaveStack[i].paint, rect)) { return false; } } return true; } // Adjust rect for all paints that may affect its geometry, then map it to identity space. Bounds adjustAndMap(SkRect rect, const SkPaint* paint) const { // Inverted rectangles really confuse our BBHs. rect.sort(); // Adjust the rect for its own paint. if (!AdjustForPaint(paint, &rect)) { // The paint could do anything to our bounds. The only safe answer is the current clip. return fCurrentClipBounds; } // Adjust rect for all the paints from the SaveLayers we're inside. if (!this->adjustForSaveLayerPaints(&rect)) { // Same deal as above. return fCurrentClipBounds; } // Map the rect back to identity space. fCTM->mapRect(&rect); // Nothing can draw outside the current clip. // (Only bounded ops call into this method, so oddballs like Clear don't matter here.) rect.intersect(fCurrentClipBounds); return rect; } // We do not guarantee anything for operations outside of the cull rect const SkRect fCullRect; // Conservative identity-space bounds for each op in the SkRecord. SkAutoTMalloc<Bounds> fBounds; // We walk fCurrentOp through the SkRecord, as we go using updateCTM() // and updateClipBounds() to maintain the exact CTM (fCTM) and conservative // identity-space bounds of the current clip (fCurrentClipBounds). unsigned fCurrentOp; const SkMatrix* fCTM; Bounds fCurrentClipBounds; // Used to track the bounds of Save/Restore blocks and the control ops inside them. SkTDArray<SaveBounds> fSaveStack; SkTDArray<unsigned> fControlIndices; }; } // namespace SkRecords