Exemple #1
0
void updateGUI()
{
	// update gui components:
	// + song played and total time
	// + song title scroll thing
	// + song position bar
	// + shuffle state
	// + repeat state
	// + volume

	// song title scroll thing
	updateSongTitle();

	if (status == NULL)
		return;

	char *timeline = (char*)malloc(32);
	sprintf(timeline,"%02i:%02i:%02i/%02i:%02i:%02i",status->elapsedTime/3600,status->elapsedTime/60,status->elapsedTime%60,status->totalTime/3600,status->totalTime/60,status->totalTime%60);
	drawPicture(screen,"songtimebg.bmp",80,20);
	drawText(screen, timeline, 80, 20, 255, 255, 255);

	char *infoline = (char*)malloc(32);
	sprintf(infoline, "%d Kbps/%d kHz", status->bitRate, status->sampleRate);
	drawPicture(screen,"songinfobg.bmp",80,40);
	drawText(screen, infoline, 80, 40, 255, 255, 255);

	float perc = status->elapsedTime<status->totalTime ?100.0*status->elapsedTime/status->totalTime :100.0;
	drawPicture(screen,"songposbg.bmp",20,120);
	drawPicture(screen,"cursor.bmp",(int)(20 + (perc * 3)),120);

	if (status->random == 0) {
		drawPicture(screen,"shuffle_false.bmp",20,160);
	}
	else {
		drawPicture(screen,"shuffle_true.bmp",20,160);
	}
	
	if (status->repeat == 0) {
		drawPicture(screen,"repeat_false.bmp",160,160);
	}
	else {
		drawPicture(screen,"repeat_true.bmp",160,160);
	}

	drawPicture(screen,"volumebg.bmp",200,200);
	drawPicture(screen,"cursor.bmp",200 + status->volume,200);

	free(timeline);
	free(infoline);
}
void FrameBufferSkPictureCanvasLayerTextureUpdater::updateTextureRect(CCGraphicsContext* context, TextureAllocator* allocator, ManagedTexture* texture, const IntRect& sourceRect, const IntRect& destRect)
{
    GraphicsContext3D* context3d = context->context3D();
    if (!context3d) {
        // FIXME: Implement this path for software compositing.
        return;
    }

    // Make sure ganesh uses the correct GL context.
    context3d->makeContextCurrent();
    // Notify ganesh to sync its internal GL state.
    context3d->grContext()->resetContext();

    // Create an accelerated canvas to draw on.
    OwnPtr<SkCanvas> canvas = createAcceleratedCanvas(context3d, allocator, texture);

    // The compositor expects the textures to be upside-down so it can flip
    // the final composited image. Ganesh renders the image upright so we
    // need to do a y-flip.
    canvas->translate(0.0, texture->size().height());
    canvas->scale(1.0, -1.0);
    // Only the region corresponding to destRect on the texture must be updated.
    canvas->clipRect(SkRect(destRect));
    // Translate the origin of contentRect to that of destRect.
    // Note that destRect is defined relative to sourceRect.
    canvas->translate(contentRect().x() - sourceRect.x() + destRect.x(),
                      contentRect().y() - sourceRect.y() + destRect.y());
    drawPicture(canvas.get());

    // Flush ganesh context so that all the rendered stuff appears on the texture.
    context3d->grContext()->flush();
}
Exemple #3
0
void BitmapSkPictureCanvasLayerTextureUpdater::paintContentsRect(SkCanvas* canvas, const IntRect& sourceRect)
{
    // Translate the origin of contentRect to that of sourceRect.
    canvas->translate(contentRect().x() - sourceRect.x(),
                      contentRect().y() - sourceRect.y());
    drawPicture(canvas);
}
void lose()
{
	drawPicture(end);
	drawString(150, 0, "Press Start", YELLOW);
	drawString(130, 0, ":( YOU LOST, TRY AGAIN?", YELLOW);
	while(!KEY_DOWN_NOW(BUTTON_START));
	while(KEY_DOWN_NOW(BUTTON_START));
}
Exemple #5
0
int main() {

  screen s;
  color c;

  c.red = 0;
  c.green = 255;
  c.blue = 255;

  int i, j;

  for( i=0; i<XRES; i++) 
    for ( j=0; j<YRES; j++) {
      /*
      c.red = random() % (MAX_COLOR + 1);
      c.green = random() % (MAX_COLOR + 1);
      c.blue = random() % (MAX_COLOR + 1);
      */
      c.red= 190; 
      c.blue =150; 
      c.green=175; 
      plot( s, c, i, j);
    }

  c.blue=255; 
  c.red =0; 
  c.green = 150; 

  printf("Matrix Testing Area. Please stand well out of range of the matrix that is about to happen.\n"); 

  printf("Making a 3X6 matrix.\n\n"); 
  struct matrix* testing = new_matrix(3,6); 
  add_edge(testing, 1, 11, 1, 2, 12, 1); 
  add_edge(testing, 3, 13, 1, 4, 14, 1); 
  add_edge(testing, 5, 15, 1, 6, 16, 1); 

  printf("Points made. Print test.\n"); 
  print_matrix(testing); 
  printf("Scalar Multiplication Test:\n"); 
  scalar_mult(3, testing); 
  print_matrix(testing); 

  printf("Identity test. Time to face the facts.\n"); 
  struct matrix* identity = new_matrix(6, 6); 
  ident(identity); 
  print_matrix(identity); 

  printf("Testing matrix multiplication. Prepare your eyes. Multiplying by the identity matrix now.\n"); 
  matrix_mult(testing, identity); 
  print_matrix(identity); 


  drawPicture(s, c); 
  display( s );    
  save_ppm(s,  "image" );
  save_extension(s, "image.jpg");
  
}  
Exemple #6
0
void buildGUI()
{
	drawPicture(screen,"background.bmp",0,0);
	
	SDL_Flip(screen);
	
	drawPicture(screen,"songposbg.bmp",20,120);
	drawPicture(screen,"volumebg.bmp",200,200);

	drawText(screen, "Shuffle", 60, 160, 255, 255, 255);
	drawText(screen, "Repeat", 200, 160, 255, 255, 255);

	drawText(screen, "[ |< ]", 20, 200, 255, 255, 255);
	drawText(screen, "[>/||]", 80, 200, 255, 255, 255);
	drawText(screen, "[ >| ]", 140, 200, 255, 255, 255);

	SDL_Flip(screen);
}
void win()
{
	drawPicture(bg);

	drawString(70, 10, ":) YOU WIN!!!", YELLOW);
	drawString(90, 10, "Press Start", YELLOW);
	while(!KEY_DOWN_NOW(BUTTON_START));
	while(KEY_DOWN_NOW(BUTTON_START));
}
void BitmapSkPictureCanvasLayerTextureUpdater::paintContentsRect(SkCanvas* canvas, const IntRect& sourceRect, CCRenderingStats& stats)
{
    // Translate the origin of contentRect to that of sourceRect.
    canvas->translate(contentRect().x() - sourceRect.x(),
                      contentRect().y() - sourceRect.y());
    double rasterizeBeginTime = monotonicallyIncreasingTime();
    drawPicture(canvas);
    stats.totalRasterizeTimeInSeconds += monotonicallyIncreasingTime() - rasterizeBeginTime;
}
Exemple #9
0
void FindCanvas::drawLayers(LayerAndroid* layer) {
#if USE(ACCELERATED_COMPOSITING)
    SkPicture* picture = layer->picture();
    if (picture) {
        setLayerId(layer->uniqueId());
        drawPicture(*picture);
    }
    for (int i = 0; i < layer->countChildren(); i++)
        drawLayers(layer->getChild(i));
#endif
}
Exemple #10
0
void GfxPaint16::kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, bool animationBlackoutFlag, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo) {
	Port *oldPort = _ports->setPort((Port *)_ports->_picWind);

	if (_ports->isFrontWindow(_ports->_picWind)) {
		_screen->_picNotValid = 1;
		drawPicture(pictureId, animationNr, mirroredFlag, addToFlag, EGApaletteNo);
		_transitions->setup(animationNr, animationBlackoutFlag);
	} else {
		// We need to set it for SCI1EARLY+ (sierra sci also did so), otherwise we get at least the following issues:
		//  LSL5 (english) - last wakeup (taj mahal flute dream)
		//  SQ5 (english v1.03) - during the scene following the scrubbing
		//   in both situations a window is shown when kDrawPic is called, which would result otherwise in
		//   no showpic getting called from kAnimate and we would get graphic corruption
		// XMAS1990 EGA did not set it in this case, VGA did
		if (getSciVersion() >= SCI_VERSION_1_EARLY)
			_screen->_picNotValid = 1;
		_ports->beginUpdate(_ports->_picWind);
		drawPicture(pictureId, animationNr, mirroredFlag, addToFlag, EGApaletteNo);
		_ports->endUpdate(_ports->_picWind);
	}
	_ports->setPort(oldPort);
}
Exemple #11
0
void CSearchDlg::OnPaint()
{
	//CPaintDC dc(this); // device context for painting
	// TODO: 在此处添加消息处理程序代码
	// 不为绘图消息调用 CDialog::OnPaint()
	//CDialog::OnPaint();
	
		  CPaintDC  dc(this);   
          CRect  rect;   
          GetClientRect(&rect);   
          CDC  dcMem;   
          dcMem.CreateCompatibleDC(&dc);   
          CBitmap  bmpBackground;   
          bmpBackground.LoadBitmap(IDB_BITMAP17);   
		  //IDB_BITMAP7是图对应的ID,设置背景图片
                  
          BITMAP   bitmap;   
          bmpBackground.GetBitmap(&bitmap);   
          CBitmap   *pbmpOld=dcMem.SelectObject(&bmpBackground); 
		  dc.SetStretchBltMode(COLORONCOLOR);
          dc.StretchBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,   
		  bitmap.bmWidth,bitmap.bmHeight,SRCCOPY); 
		  //设置背景图片
	
	
	
	
		CPaintDC   dc_1(this);   
		CRect   rect_1;   
	    GetClientRect(&rect_1);   
		CDC   dcMem_1;
		dcMem_1.CreateCompatibleDC(&dc_1); 
		drawPicture(&m_Pic1, 0);
		drawPicture(&m_Pic2, 1);
		drawPicture(&m_Pic3, 2);
		drawPicture(&m_Pic4, 3);
	//绘制照片

}
Exemple #12
0
void MainWindow::on_actionCamera1_triggered(){
	subCamWindow1 = new QMdiSubWindow;
	camWindow1 = new CameraWindow();
	int ip[] = {192,168,1,3};
	cameraHandler1->initCameraByIp(ip);
	cameraHandler1->start();

	connect(cameraHandler1, SIGNAL(gotCameraImage(QImage)), camWindow1, SLOT(drawPicture(QImage)));

	subCamWindow1->setWidget(camWindow1);
	subCamWindow1->setAttribute(Qt::WA_DeleteOnClose);
	ui.mdiArea->addSubWindow(subCamWindow1);
	camWindow1->show();
}
int splash()
{
	int seed = 0;
	//u16 *ptr = videoBuffer;
	REG_DISPCTL = MODE3 | BG2_ENABLE;
	drawPicture(start);
	drawString(150, 0, "Press Start", YELLOW);
	while(!KEY_DOWN_NOW(BUTTON_START))
	{
		seed++;
	}
	while(KEY_DOWN_NOW(BUTTON_START));
	return seed;
}
InfoBoxTemple::InfoBoxTemple( Widget* parent, const Tile& tile )
  : GuiInfoBox( parent, Rect( 0, 0, 510, 256 ), -1 ), _td( new Impl )
{
  _td->font = Font::create( FONT_2 );
  _td->temple = tile.getTerrain().getOverlay().as<Temple>();
  RomeDivinityPtr divn = _td->temple->getDivinity();

  std::string text = StringHelper::format( 0xff, "##Temple of ##%s (%s)", 
                                                 divn->getName().c_str(), 
                                                 divn->getShortDescription().c_str() );
  setTitle( text );

  drawWorkers();
  drawPicture();
}
BOOL CMyDrawPictureClass::PreTranslateMessage(MSG* pMsg)
{
	// TODO: 在此添加专用代码和/或调用基类
	if(pMsg->message==WM_LBUTTONDOWN&&m_IsPicLoaded)
	{
		CWnd * hwnd;
		POINT pointGetCtl;
		GetCursorPos(&pointGetCtl);
		hwnd= (CWnd *)WindowFromPoint(pointGetCtl);
		while (hwnd && hwnd->GetParent()!=this)
			hwnd = hwnd->GetParent();
		if(GetDlgItem(IDC_STATIC_BASECOLOR1)==hwnd)
		{
			if(!m_IsMakePic)
			{
				m_OldSursor = ::GetCursor();
				m_IsMakePic= true;
			}
			
		}
		else
		{

			if(m_IsMakePic)
			{
				::SetCursor(m_OldSursor);
				m_IsMakePic = false;

				COLORREF color;
				color = ::GetPixel(::GetDC(NULL),pMsg->pt.x,pMsg->pt.y);
				CString wndColor=_T("0");
				wndColor.Format(_T("%x"),color);
				m_BaseColor1.SetBkColor(color);
				wndColor.MakeUpper();
				this->GetDlgItem(IDC_EDIT_COLOR1)->SetWindowTextW(wndColor);

				////////设置前台色///////////////////
				m_ForegroundColor = color;

				m_IsPicLoaded = true;
				
				drawPicture();
			}
		}
	}

	return CMFCPropertyPage::PreTranslateMessage(pMsg);
}
void kapalterbang::draw(){
	//TODO nanti harus diganti
	if (!isDead()) {
		if (isExploding()) {
			drawPicture(getX(),getY(),3,200,"explosion.txt","explosioncolor.txt");
			deadlifetime--;
		} else {
			//drawPicture(x,y,3,200,"plane2.txt",colorFileName);
			polygon bodydraw = body.hasilSkala(scale,scale);
			polygon windraw = window.hasilSkala(scale,scale);
			bodydraw.draw(x,y,255,255,255,255,false);
			windraw.draw(x,y,0,0,0,255,false);


		}
	}
		//drawText("BOOM",4,getX(),getY(),2,255,0,0,255);
	
}
Exemple #17
0
/** Funkcja dekodująca plik DT alorytmem LZW
@param name_save nazwa pliku DT
 */
void Reader::readIndexesFromPixels(string name_save){
    maxColors = maxColors + 1;
    int length = pixelWidth;
    int dictionaryIndex;
    char * buffer = new char [length];
    string helpReader;
    string characters;
    string word;

    plik.seekg(pictureStart-1,ios::beg);
    plik.read(buffer,length);
    helpReader = charToString(buffer,length);
    int firstIndex = bin2dec(helpReader);
    characters = dictionaryColors[firstIndex];

    while(!plik.fail()){
        plik.read(buffer,length);
        helpReader = charToString(buffer,length);
        dictionaryIndex = bin2dec(helpReader);

        if (dictionaryColors.count(dictionaryIndex)){
          word = dictionaryColors[dictionaryIndex];
        }
        else if (dictionaryIndex == maxColors){
            word = characters + characters.substr(0,24);
        }
        else{
          throw "Decoding problem!";
        }

        binaryPixelToRGB(word);
        dictionaryColors[maxColors++] = characters + word.substr(0,24);
        characters = word;
  }

        drawPicture(name_save);
}
Exemple #18
0
void updateSongTitle()
{
	char *Text = songname;
	int Length = strlen(Text);
	int i;
	int k;
	char *Word;
	Word = (char *)malloc(400);
	
	int linelength = 28;

	i = scrollpos;
	if (i <= Length) {
		for(k = 0; k < linelength; k++)
		{
			if (i + k + 1 >= Length) {
				// start over again from beginning of string
				Word[k] = Text[(i + k) - Length + 1];
			}
			else {
				Word[k] = Text[i + k + 1];
			}
		}
		Word[k] = '\0';
		scrollpos++;

		drawPicture(screen,"songtitlebg.bmp",20,80);
		drawText(screen, Word, 20, 80, 255, 255, 255);
	}
	else {
		scrollpos = 0;
	}

	free(Word);

}
Exemple #19
0
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
void CMyDrawPictureClass::OnBnClickedButtonChangeoffsetcolor()
{
	// TODO: 在此添加控件通知处理程序代码
	drawPicture();
}
Exemple #21
0
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
Exemple #22
0
void GfxFrameout::kernelFrameout() {
	if (g_sci->_robotDecoder->isVideoLoaded()) {
		showVideo();
		return;
	}

	_palette->palVaryUpdate();

	for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) {
		reg_t planeObject = it->object;

		// Draw any plane lines, if they exist
		// These are drawn on invisible planes as well. (e.g. "invisiblePlane" in LSL6 hires)
		// FIXME: Lines aren't always drawn (e.g. when the narrator speaks in LSL6 hires).
		// Perhaps something is painted over them?
		for (PlaneLineList::iterator it2 = it->lines.begin(); it2 != it->lines.end(); ++it2) {
			Common::Point startPoint = it2->startPoint;
			Common::Point endPoint = it2->endPoint;
			_coordAdjuster->kernelLocalToGlobal(startPoint.x, startPoint.y, it->object);
			_coordAdjuster->kernelLocalToGlobal(endPoint.x, endPoint.y, it->object);
			_screen->drawLine(startPoint, endPoint, it2->color, it2->priority, it2->control);
		}

		int16 planeLastPriority = it->lastPriority;

		// Update priority here, sq6 sets it w/o UpdatePlane
		int16 planePriority = it->priority = readSelectorValue(_segMan, planeObject, SELECTOR(priority));

		it->lastPriority = planePriority;
		if (planePriority < 0) { // Plane currently not meant to be shown
			// If plane was shown before, delete plane rect
			if (planePriority != planeLastPriority)
				_paint32->fillRect(it->planeRect, 0);
			continue;
		}

		// There is a race condition lurking in SQ6, which causes the game to hang in the intro, when teleporting to Polysorbate LX.
		// Since I first wrote the patch, the race has stopped occurring for me though.
		// I'll leave this for investigation later, when someone can reproduce.
		//if (it->pictureId == kPlanePlainColored)	// FIXME: This is what SSCI does, and fixes the intro of LSL7, but breaks the dialogs in GK1 (adds black boxes)
		if (it->pictureId == kPlanePlainColored && (it->planeBack || g_sci->getGameId() != GID_GK1))
			_paint32->fillRect(it->planeRect, it->planeBack);

		_coordAdjuster->pictureSetDisplayArea(it->planeRect);
		// Invoking drewPicture() with an invalid picture ID in SCI32 results in
		// invalidating the palVary palette when a palVary effect is active. This
		// is quite obvious in QFG4, where the day time palette is incorrectly
		// shown when exiting the caves, and the correct night time palette
		// flashes briefly each time that kPalVaryInit is called.
		if (it->pictureId != 0xFFFF)
			_palette->drewPicture(it->pictureId);

		FrameoutList itemList;

		createPlaneItemList(planeObject, itemList);

		for (FrameoutList::iterator listIterator = itemList.begin(); listIterator != itemList.end(); listIterator++) {
			FrameoutEntry *itemEntry = *listIterator;

			if (!itemEntry->visible)
				continue;

			if (itemEntry->object.isNull()) {
				// Picture cel data
				_coordAdjuster->fromScriptToDisplay(itemEntry->y, itemEntry->x);
				_coordAdjuster->fromScriptToDisplay(itemEntry->picStartY, itemEntry->picStartX);

				if (!isPictureOutOfView(itemEntry, it->planeRect, it->planeOffsetX, it->planeOffsetY))
					drawPicture(itemEntry, it->planeOffsetX, it->planeOffsetY, it->planePictureMirrored);
			} else {
				GfxView *view = (itemEntry->viewId != 0xFFFF) ? _cache->getView(itemEntry->viewId) : NULL;
				int16 dummyX = 0;

				if (view && view->isSci2Hires()) {
					view->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x);
					view->adjustToUpscaledCoordinates(itemEntry->z, dummyX);
				} else if (getSciVersion() >= SCI_VERSION_2_1) {
					_coordAdjuster->fromScriptToDisplay(itemEntry->y, itemEntry->x);
					_coordAdjuster->fromScriptToDisplay(itemEntry->z, dummyX);
				}

				// Adjust according to current scroll position
				itemEntry->x -= it->planeOffsetX;
				itemEntry->y -= it->planeOffsetY;

				uint16 useInsetRect = readSelectorValue(_segMan, itemEntry->object, SELECTOR(useInsetRect));
				if (useInsetRect) {
					itemEntry->celRect.top = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inTop));
					itemEntry->celRect.left = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inLeft));
					itemEntry->celRect.bottom = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inBottom));
					itemEntry->celRect.right = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inRight));
					if (view && view->isSci2Hires()) {
						view->adjustToUpscaledCoordinates(itemEntry->celRect.top, itemEntry->celRect.left);
						view->adjustToUpscaledCoordinates(itemEntry->celRect.bottom, itemEntry->celRect.right);
					}
					itemEntry->celRect.translate(itemEntry->x, itemEntry->y);
					// TODO: maybe we should clip the cels rect with this, i'm not sure
					//  the only currently known usage is game menu of gk1
				} else if (view) {
					// Process global scaling, if needed.
					// TODO: Seems like SCI32 always processes global scaling for scaled objects
					// TODO: We can only process symmetrical scaling for now (i.e. same value for scaleX/scaleY)
					if ((itemEntry->scaleSignal & kScaleSignalDoScaling32) && 
					   !(itemEntry->scaleSignal & kScaleSignalDisableGlobalScaling32) &&
					    (itemEntry->scaleX == itemEntry->scaleY) &&
						itemEntry->scaleX != 128)
						applyGlobalScaling(itemEntry, it->planeRect, view->getHeight(itemEntry->loopNo, itemEntry->celNo));

					if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128))
						view->getCelRect(itemEntry->loopNo, itemEntry->celNo,
							itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->celRect);
					else
						view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo,
							itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX,
							itemEntry->scaleY, itemEntry->celRect);

					Common::Rect nsRect = itemEntry->celRect;
					// Translate back to actual coordinate within scrollable plane
					nsRect.translate(it->planeOffsetX, it->planeOffsetY);

					if (g_sci->getGameId() == GID_PHANTASMAGORIA2) {
						// HACK: Some (?) objects in Phantasmagoria 2 have no NS rect. Skip them for now.
						// TODO: Remove once we figure out how Phantasmagoria 2 draws objects on screen.
						if (lookupSelector(_segMan, itemEntry->object, SELECTOR(nsLeft), NULL, NULL) != kSelectorVariable)
							continue;
					}

					if (view && view->isSci2Hires()) {
						view->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left);
						view->adjustBackUpscaledCoordinates(nsRect.bottom, nsRect.right);
						g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect);
					} else if (getSciVersion() >= SCI_VERSION_2_1 && _resMan->detectHires()) {
						_coordAdjuster->fromDisplayToScript(nsRect.top, nsRect.left);
						_coordAdjuster->fromDisplayToScript(nsRect.bottom, nsRect.right);
						g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect);
					}
				}

				// Don't attempt to draw sprites that are outside the visible
				// screen area. An example is the random people walking in
				// Jackson Square in GK1.
				if (itemEntry->celRect.bottom < 0 || itemEntry->celRect.top  >= _screen->getDisplayHeight() ||
				    itemEntry->celRect.right  < 0 || itemEntry->celRect.left >= _screen->getDisplayWidth())
					continue;

				Common::Rect clipRect, translatedClipRect;
				clipRect = itemEntry->celRect;

				if (view && view->isSci2Hires()) {
					clipRect.clip(it->upscaledPlaneClipRect);
					translatedClipRect = clipRect;
					translatedClipRect.translate(it->upscaledPlaneRect.left, it->upscaledPlaneRect.top);
				} else {
					// QFG4 passes invalid rectangles when a battle is starting
					if (!clipRect.isValidRect())
						continue;
					clipRect.clip(it->planeClipRect);
					translatedClipRect = clipRect;
					translatedClipRect.translate(it->planeRect.left, it->planeRect.top);
				}

				if (view) {
					if (!clipRect.isEmpty()) {
						if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128))
							view->draw(itemEntry->celRect, clipRect, translatedClipRect,
								itemEntry->loopNo, itemEntry->celNo, 255, 0, view->isSci2Hires());
						else
							view->drawScaled(itemEntry->celRect, clipRect, translatedClipRect,
								itemEntry->loopNo, itemEntry->celNo, 255, itemEntry->scaleX, itemEntry->scaleY);
					}
				}

				// Draw text, if it exists
				if (lookupSelector(_segMan, itemEntry->object, SELECTOR(text), NULL, NULL) == kSelectorVariable) {
					g_sci->_gfxText32->drawTextBitmap(itemEntry->x, itemEntry->y, it->planeRect, itemEntry->object);
				}
			}
		}

		for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) {
			if (pictureIt->object == planeObject) {
				delete[] pictureIt->pictureCels;
				pictureIt->pictureCels = 0;
			}
		}
	}

	showCurrentScrollText();

	_screen->copyToScreen();

	g_sci->getEngineState()->_throttleTrigger = true;
}
Exemple #23
0
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
int game(int seed)
{
	REG_DISPCTL = MODE3 | BG2_ENABLE;
	int live = 5;
	char buffer[41];
	int speed = 1;

	int num = 100;
	int objx = 70;
	int objy = 50;

	drawPicture(black);
	
	WALL wall0;
	wall0.i = 80;
	wall0.gate = 90;
	wall0.gateSize = 10;
	wall0.color = WHITE;
	
	WALL wall1;
	wall1.i = 100;
	wall1.gate = 90;
	wall1.gateSize = 10;
	wall1.color = MAGENTA;

	WALL wall2;
	wall2.i = 120;
	wall2.gate = 30;
	wall2.gateSize = 30;
	wall2.color = RED;
	
	WALL wall3;
	wall3.i = 140;
	wall3.gate = 150;
	wall3.gateSize = 30;
	wall3.color = BLUE;

	WALL wall4;
	wall4.i = 160;
	wall4.gate = 0;
	wall4.gateSize = 20;
	wall4.color = GREEN;

	WALL wall5;
	wall5.i = 180;
	wall5.gate = 130;
	wall5.gateSize = 20;
	wall5.color = BLUE;
	
	WALL wall6;
	wall6.i = 200;
	wall6.gate = 130;
	wall6.gateSize = 15;
	wall6.color = CYAN;
	

	// Game Loop
	while(1)
	{
		
		int oldx = objx;
		int oldy = objy;
		
		drawRect(oldx,oldy,1,1, BLACK);


		if(KEY_DOWN_NOW(BUTTON_SELECT))
		{	
			
		 	objx = 70;
			objy = 50;
			live = 5;
			drawRect(150,0,60,30,BLACK);
			drawString(150, 0, "Score: 0", YELLOW);

		}
		
				
		if(KEY_DOWN_NOW(BUTTON_UP))
		{
			objx-=speed;
			if(objx < 0)
			{
				objx = 0;
			}
			
		}
		if(KEY_DOWN_NOW(BUTTON_DOWN))
		{
			objx+=speed;
			if(objx > 159)
			{
				objx = 159;
			}
		
		}
		
		if(KEY_DOWN_NOW(BUTTON_A))
		{
			speed = 2;
		
		}
		if(KEY_DOWN_NOW(BUTTON_B))
		{
			speed = 1;
			
		}
		if(KEY_DOWN_NOW(BUTTON_RIGHT))
		{
			objy++;
	
		}
		if(KEY_DOWN_NOW(BUTTON_LEFT))
		{
			objy--;
			if(objy <= 0)
			{
				objy= 0;
			}
	
		}
	
		drawRect(objx,objy,1,1, RED);
		
		drawWall(wall0.i, wall0.gate, wall0.gateSize, wall0.color);
		
		if(num < 50) 
		{
			if(num <= 0)
			{
				num = 100;
			}
			
			drawWall(wall1.i, wall1.gate++, wall1.gateSize, wall1.color);
			drawWall(wall2.i, wall2.gate-=2, wall2.gateSize, wall2.color);
			drawWall(wall3.i, wall3.gate+=3, wall3.gateSize, wall3.color);
			drawWall(wall4.i, wall4.gate-=3, wall4.gateSize, wall4.color);
			drawWall(wall5.i, wall5.gate+=3, wall5.gateSize, wall5.color);
			drawWall(wall6.i, wall6.gate+=3, wall6.gateSize, wall6.color);
		}
		else 
		{
			drawWall(wall1.i, wall1.gate--, wall1.gateSize, wall1.color);
			drawWall(wall2.i, wall2.gate+=2, wall2.gateSize, wall2.color);
			drawWall(wall3.i, wall3.gate-=3, wall3.gateSize, wall3.color);
			drawWall(wall4.i, wall4.gate+=3, wall4.gateSize, wall4.color);
			drawWall(wall5.i, wall5.gate-=3, wall5.gateSize, wall5.color);
			drawWall(wall6.i, wall6.gate-=3, wall6.gateSize, wall6.color);
		}
		num--;
		
		if(objy < wall0.i)
		{
			drawString(150, 0, "Score: 0", YELLOW);
		}

		if(objy == wall0.i)
		{
			if(objx < wall0.gate || objx > wall0.gate + wall0.gateSize)
			{
				live--;
				objy-=10;
				drawRect(objx,objy ,1,1, RED);

				if (live == 0)
				{
					return LOSE;
				}
			}
			drawRect(150,0,60,30,BLACK);
			
			drawString(150, 0, "Score: 1", YELLOW);
		}
		if(objy == wall1.i)
		{
			if(objx < wall1.gate || objx > wall1.gate + wall1.gateSize)
			{
				live--;
				objy-=10;
				drawRect(objx,objy ,1,1, RED);
				if (live == 0)
				{
					return LOSE;
				}
			}
			drawRect(150,0,60,30,BLACK);
			drawString(150, 0, "Score: 2", YELLOW);
		}
		if(objy == wall2.i)
		{
			if(objx < wall2.gate || objx > wall2.gate + wall2.gateSize)
			{
				live--;
				objy-=10;
				drawRect(objx,objy ,1,1, RED);
				if (live == 0)
				{
					return LOSE;
				}
			}
			drawRect(150,0,60,30,BLACK);
			drawString(150, 0, "Score: 3", YELLOW);
		}
		if(objy == wall3.i)
		{
			if(objx < wall3.gate || objx > wall3.gate + wall3.gateSize)
			{
				live--;
				objy-=10;
				drawRect(objx,objy ,1,1, RED);
				if (live == 0)
				{
					return LOSE;
				}
			}
			drawRect(150,0,60,30,BLACK);
			drawString(150, 0, "Score: 4", YELLOW);
		}
		if(objy == wall4.i)
		{
			if(objx < wall4.gate || objx > wall4.gate + wall4.gateSize)
			{
				live--;
				objy-=10;
				drawRect(objx,objy ,1,1, RED);
				if (live == 0)
				{
					return LOSE;
				}
			}
			drawRect(150,0,60,30,BLACK);
			drawString(150, 0, "Score: 5", YELLOW);
		}
		if(objy == wall5.i)
		{
			if(objx < wall5.gate || objx > wall5.gate + wall5.gateSize)
			{
				live--;
				objy-=10;
				drawRect(objx,objy ,1,1, RED);
				if (live == 0)
				{
					return LOSE;
				}
			}
			drawRect(150,0,60,30,BLACK);
			drawString(150, 0, "Score: 6", YELLOW);
		}
		if(objy == wall6.i)
		{
			if(objx < wall6.gate || objx > wall6.gate + wall6.gateSize)
			{
				live--;
				objy-=10;
				drawRect(objx,objy ,1,1, RED);
				if (live == 0)
				{
					return LOSE;
				}
			}
			drawRect(150,0,60,30,BLACK);
			drawString(150, 0, "Score: 7", YELLOW);
		}
		
		if(objy > wall6.i +5)
		{
			return WIN;
		}
		drawRect(5,5,60,30,BLACK);
		waitForVblank();
		drawImage3(0,0,30,30,heart);
		sprintf(buffer, " %d", live);
		drawString(10, 30, buffer, YELLOW);
		drawString(80,210, "EXIT", YELLOW);
	
		
	}

		
}
Exemple #25
0
	void View::draw2D() const
	{
		// Save current states
		::glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT);
		// Disable depth test to avoid having the overlay hidden
		::glDisable(GL_DEPTH_TEST);

		// Set view matrices for 2D overlay display
		::glMatrixMode(GL_PROJECTION);
		::glPushMatrix();
		::glLoadIdentity();
		// Window coordinates : [0,0] at top-left, [width,height] at bottom-right
		::gluOrtho2D(0.0f, pWidth, pHeight, 0.0f);

		::glMatrixMode(GL_MODELVIEW);
		::glPushMatrix();
		::glLoadIdentity();

		// Alpha blending
		::glEnable(GL_BLEND);
		::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		// Draw the overlays
		for (auto picOverlay : pPictures)
			drawOverlay(*picOverlay);

		for (auto textOverlay : pTexts)
			drawOverlay(*textOverlay);

		// Render the control tree
		if (!(!pControl) and pControl->visible())
		{
			if (!pUISurface)
			{
				// Avoid texture creation with a 0 dimension
				pUISurface = new DrawingSurface(Math::Max(pControl->width(), 1.0f),
					Math::Max(pControl->height(), 1.0f));
				pUISurface->begin();
				pControl->draw(pUISurface);
				pUISurface->commit();
			}
			else if (pControl->modified())
			{
				pUISurface->resize(Math::Max(pControl->width(), 1.0f),
					Math::Max(pControl->height(), 1.0f));
				pUISurface->begin();
				pControl->draw(pUISurface);
				pUISurface->commit();
			}

			if (pPictureShaders and pPictureShaders->valid())
			{
				drawPicture(pUISurface->texture(), pControl->x(), pControl->y(),
							pControl->width(), pControl->height(), true, true);
			}
		}

		// Reset matrices
		::glMatrixMode(GL_PROJECTION);
		::glPopMatrix();
		::glMatrixMode(GL_MODELVIEW);
		::glPopMatrix();

		// Restore enable settings
		::glPopAttrib();
	}
void GfxGlEngine::drawPicture( const Picture &picture, const Point& pos, Rect* clipRect )
{
  drawPicture( picture, pos.getX(), pos.getY() );
}
Exemple #27
0
int main()
{
    drawPicture();
    return 0;
}