void TexturedObjectScrollView::draw(){

	#if(BENCH_TEXTURED_OBJECT_SCROLLVIEW)
	TS_START_ACC("TOScrollView d");
	#endif
	glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
	fbo.draw(0,0);
	ofEnableBlendMode(OF_BLENDMODE_ALPHA);

	//scroll handle math
	float scrollAreaViewable = canvas.width / (layoutWidth );
	float scrollHandleW = ofClamp(canvas.width * scrollAreaViewable, 0, config.maxScrollHandleW);
	ofRectangle scrollHandle = ofRectangle(0,0, scrollHandleW, config.scrollHandleH );
	float scrollHandlePad = 4;
	float maxX = (canvas.width - scrollHandle.width) - 2 * config.scrollHandlePad;
	float scrollPercent = ofClamp( xOffset / (layoutWidth  - canvas.width), 0, 1);
	scrollHandle.x = config.scrollHandlePad + scrollPercent * maxX;
	scrollHandle.y = canvas.height - config.scrollHandleH * 0.5f + config.scrollHandleVertPostion;
	if(scrollHandleAlpha > 1.0f) scrollHandleAlpha = 1.0f;
	if(fboDirty < 0.1){
		scrollHandleAlpha *= 0.8;
	}

	//draw scroll handle
	if(scrollHandleAlpha > 0.01){
		ofSetColor(config.scrollHandleColor, scrollHandleAlpha * 255);
		ofDrawRectangle(scrollHandle);
		ofSetColor(255);
	}
	#if(BENCH_TEXTURED_OBJECT_SCROLLVIEW)
	TS_STOP_ACC("TOScrollView d");
	#endif
}
void TexturedObjectScrollView::updateFbo(){

	#if(BENCH_TEXTURED_OBJECT_SCROLLVIEW)
	TS_START_ACC("TexturedObjectScrollView u");
	#endif
	fbo.begin();
	ofClear(config.bgColor);
	
	ofPushMatrix();
	ofTranslate(-xOffset, 0);

	for(size_t i = 0; i < objects.size(); i++){

		if(layout[i].enabled){
			ofRectangle rWithOffset = layout[i].placement;
			//rWithOffset.x += extraLeftSpaceTarget;
			bool onView = scrollCanvas.intersects(rWithOffset);
			if(onView){
				//layout[i].texObject->getTexture(sizeToLoad, 0)->draw(rWithOffset);
				int texIndex = layout[i].texObjTex.texIndex;

				DrawTileInfo dti;
				if(config.customTileDraw){
					dti.area = rWithOffset;
					dti.who = this;
					dti.alpha = 0.0;
					dti.layoutID = i;
					dti.objTex = layout[i].texObjTex;
				}

				if(layout[i].texObjTex.texObj->isReadyToDraw(config.sizeToLoad, texIndex)){
					float a = layout[i].fade.val();
					ofSetColor(255, 255 * a);
					layout[i].texObjTex.texObj->getRealTexture(config.sizeToLoad, texIndex)->draw(rWithOffset);
					dti.alpha = a;
				}else{
					if(config.drawLoadingRects){
						ofSetColor(config.loadingRectColors);
						ofDrawRectangle(rWithOffset);
					}
				}
				if(config.customTileDraw){
					ofNotifyEvent(eventTileDraw, dti, this);
				}
			}
		}
	}
	ofPopMatrix();

	if(config.drawMoreContentHintGradients){
		drawScrollGradients();
	}

	fbo.end();
	#if(BENCH_TEXTURED_OBJECT_SCROLLVIEW)
	TS_STOP_ACC("TexturedObjectScrollView u");
	#endif
}
void ofApp::update(){

	TS_START("simple measurement");
		ofSleepMillis(1);
	TS_STOP("simple measurement");

	TS_START("nested measurement1");
		TS_START("nested measurement11");
			TS_START("nested measurement111");
			ofSleepMillis(1);
			TS_STOP("nested measurement111");
		TS_STOP("nested measurement11");
		TS_START("nested measurement12");
			ofSleepMillis(1);
		TS_STOP("nested measurement12");
	TS_STOP("nested measurement1");


	if (ofGetFrameNum()%60 == 1){
		TS_START_NIF("sample across frames");
	}

	if (ofGetFrameNum()%60 == 3){
		TS_STOP_NIF("sample across frames");
	}

	if (ofGetFrameNum()%600 == 30 || ofGetFrameNum() == 1){
		TS_START("some uncommon method")
			ofSleepMillis(ofRandom(3));
		TS_STOP("some uncommon method");
	}

	//test accumulation time sampling
	for(int i = 0; i < 3; i++){
		TS_START_ACC("accum test");
		ofSleepMillis(1);
		TS_STOP_ACC("accum test");
		{
			TS_SCOPE_ACC("scope measurement acc");
			ofSleepMillis(1);
		}
	}

	for(int i = myThreads.size() - 1; i >= 0 ; i--){
		if (!myThreads[i]->isThreadRunning()){
			delete myThreads[i];
			myThreads.erase(myThreads.begin() + i);
		}
	}

	{
		TS_SCOPE("scope measurement");
		ofSleepMillis(1);
	}
}
float ofxFontStash2::drawLines(const vector<StyledLine> &lines, float x, float y, bool debug){

	// if possible get rid of this translate:
	#ifndef GL_VERSION_3
	ofPushMatrix();
	ofTranslate(x, y);
	#endif

	ofVec2f offset;
	#ifdef GL_VERSION_3
	offset.x = x * pixelDensity;
	offset.y = y * pixelDensity;
	#endif

//	TS_START("count words");
//	int nDrawnWords;
//	for(int i = 0; i < lines.size(); i++){
//		for(int j = 0; j < lines[i].elements.size(); j++){
//			nDrawnWords ++;
//		}
//	}
//	TS_STOP("count words");

	//debug line heights!
	if(debug){
		TS_START("draw line Heights");
		ofSetColor(0,255,0,32);
		float yy = 0;
		for( const StyledLine &line : lines ){
			ofDrawLine(offset.x + 0.5f, offset.y + yy + 0.5f, offset.x + line.lineW + 0.5f, offset.y + yy + 0.5f);
			yy += line.lineH;
		}
		TS_STOP("draw line Heights");
	}

	ofxFontStashStyle drawStyle;
	drawStyle.fontSize = -1;

	float offY = 0.0f; // only track for return value
	TS_START("draw all lines");

	FONT_STASH_PRE_DRAW;

	#ifndef GL_VERSION_3
	if (pixelDensity != 1.0f){ //hmmmm
		ofScale(1.0f/pixelDensity, 1.0f/pixelDensity);
	}
	#endif


	for(int i = 0; i < lines.size(); i++){
		y += lines[i].lineH;
		
		for(int j = 0; j < lines[i].elements.size(); j++){

			if(lines[i].elements[j].content.type != SEPARATOR_INVISIBLE ){ //no need to draw the invisible chars

				const StyledLine &l = lines[i];
				const LineElement &el = l.elements[j];
				const string & texttt = el.content.styledText.text;

				if (el.content.styledText.style.valid &&
					drawStyle != el.content.styledText.style ){

					drawStyle = el.content.styledText.style;
					TS_START_ACC("applyStyle");
					applyStyle(drawStyle);
					TS_STOP_ACC("applyStyle");
				}
				//lines[i].elements[j].area.y += lines[i].lineH -lines[0].lineH;

				//TS_START_ACC("fonsDrawText");
				fonsDrawText(fs,
							 el.x * pixelDensity + offset.x,
							 (el.baseLineY + l.lineH - lines[0].lineH) * pixelDensity + offset.y,
							 texttt.c_str(),
							 NULL);
				//TS_STOP_ACC("fonsDrawText");

				//debug rects
				if(debug){
					//TS_START_ACC("debug rects");
					if(el.content.type == BLOCK_WORD) ofSetColor(70 * i, 255 - 70 * i, 0, 200);
					else ofSetColor(50 * i,255 - 50 * i, 0, 100);
					const ofRectangle &r = el.area;
					ofDrawRectangle(pixelDensity * r.x, pixelDensity * r.y, pixelDensity * r.width, pixelDensity * r.height);
					ofFill();
				}
			}
		}
	}
	TS_STOP("draw all lines");

	#ifndef GL_VERSION_3
	ofPopMatrix();
	#endif
	FONT_STASH_POST_DRAW;

	if(debug){
		ofSetColor(255);
	}
	return offY;
}