bool onUpdate(float timeDelta) { april::rendersys->clear(); april::rendersys->setOrthoProjection(drawRect); april::rendersys->drawFilledRect(drawRect, april::Color(64, 64, 64)); april::rendersys->setTexture(texture); april::rendersys->drawTexturedRect(textureRect + offset, grect(0.0f, 0.0f, 1.0f, 1.0f)); april::rendersys->drawFilledRect(grect(0.0f, 0.0f, 100.0f, 75.0f), april::Color::Orange); april::rendersys->drawFilledRect(grect(10.0f, 10.0f, 80.0f, 55.0f), april::Color::Yellow); return true; }
void Object::draw() { if (!this->isVisible() || heqf(this->scaleFactor.x, 0.0f, aprilui::eTolerance) || heqf(this->scaleFactor.y, 0.0f, aprilui::eTolerance)) { return; } gmat4 originalMatrix = april::rendersys->getModelviewMatrix(); grect viewport; grect orthoProjection; bool clipped = (this->clip && this->parent != NULL); if (clipped) { // TODO - this has to be implemented using clipping planes in April orthoProjection = april::rendersys->getOrthoProjection(); viewport = april::rendersys->getViewport(); grect rect = this->parent->getBoundingRect(); gvec2 ratio = orthoProjection.getSize() / viewport.getSize(); april::rendersys->setOrthoProjection(grect(-rect.getPosition(), rect.getSize())); april::rendersys->setViewport(grect((rect.getPosition() + orthoProjection.getPosition()) / ratio, rect.getSize() / ratio)); } gvec2 position = this->rect.getPosition() + this->center; if (position.x != 0.0f || position.y != 0.0f) { april::rendersys->translate(position.x, position.y); } if (this->angle != 0.0f) { april::rendersys->rotate(this->angle); } if (this->scaleFactor.x != 1.0f || this->scaleFactor.y != 1.0f) { april::rendersys->scale(this->scaleFactor.x, this->scaleFactor.y, 1.0f); } this->OnDraw(); if (aprilui::isDebugEnabled()) { this->OnDrawDebug(); } if (this->center.x != 0.0f || this->center.y != 0.0f) { april::rendersys->translate(-this->center.x, -this->center.y); } foreach (Object*, it, children) { (*it)->draw(); } if (clipped) { april::rendersys->setOrthoProjection(orthoProjection); april::rendersys->setViewport(viewport); } april::rendersys->setModelviewMatrix(originalMatrix); }
void LayerManagerOGL::WorldTransformRect(nsIntRect& aRect) { gfxRect grect(aRect.x, aRect.y, aRect.width, aRect.height); grect = mWorldMatrix.TransformBounds(grect); aRect.SetRect(grect.X(), grect.Y(), grect.Width(), grect.Height()); }
grect hstr_to_grect(chstr string) { harray<hstr> data = string.split(aprilui::SeparatorParameter); if (data.size() != 4) { throw hl_exception("Cannot convert string '" + string + "' to gtypes::Rectangle."); } return grect(data[0].trim(), data[1].trim(), data[2].trim(), data[3].trim()); }
Animator::Animator(chstr name) : Object(name, grect(0.0f, 0.0f, 1.0f, 1.0f)) { this->timeSinceLastFrame = 0.0f; this->value = 0.0f; this->animationFunction = aprilui::Object::Linear; this->timer = 0.0f; this->delay = 0.0f; this->periods = 1.0f; this->amplitude = 0.5f; this->speed = 1.0f; this->offset = 0.0f; this->acceleration = 0.0f; this->discreteStep = 0; this->reset = false; this->inheritValue = false; this->target = 0.0f; this->useTarget = false; this->customFunction = NULL; }
bool Object::isPointInside(gvec2 position) { if (heqf(this->scaleFactor.x, 0.0f, aprilui::eTolerance) || heqf(this->scaleFactor.y, 0.0f, aprilui::eTolerance)) { return false; } if (this->parent != NULL) { Object* obj = this; Object* parent = this->parent; while (parent != NULL) { if (obj->isClip() && !parent->getBoundingRect().isPointInside(position)) { return false; } obj = parent; parent = obj->getParent(); } } return grect(0.0f, 0.0f, this->rect.getSize()).isPointInside(this->transformToLocalSpace(position)); }
void Object::OnDrawDebug() { april::rendersys->drawRect(grect(-1.0f, -1.0f, 2.0f, 2.0f), april::Color::White); april::rendersys->drawRect(grect(-3.0f, -3.0f, 6.0f, 6.0f), april::Color::Green); }
void ScrollBar::notifyEvent(chstr name, void* params) { Object::notifyEvent(name, params); if (name == "AttachToObject") { Container* parent = dynamic_cast<Container*>(this->parent); if (parent == NULL) { hlog::warnf(aprilui::logTag, "ScrollBar '%s' not attached to object of class Container!", this->name.c_str()); } } else if (name == "SkinChange") { if (this->skinName != "") { if (this->buttonBegin == NULL) { this->buttonBegin = new ImageButton(aprilui::generateName("aprilui::ScrollSkinButtonBegin"), grect(0.0f, 0.0f, -1.0f, -1.0f)); this->registerChild(this->buttonBegin); _SET_CLICK_EVENT_FUNCTION(this->buttonBegin, _clickScrollBegin); this->buttonEnd = new ImageButton(aprilui::generateName("aprilui::ScrollSkinButtonEnd"), grect(0.0f, 0.0f, -1.0f, -1.0f)); this->registerChild(this->buttonEnd); _SET_CLICK_EVENT_FUNCTION(this->buttonEnd, _clickScrollEnd); this->buttonBack = new ImageButton(aprilui::generateName("aprilui::ScrollSkinButtonBack"), grect(0.0f, 0.0f, -1.0f, -1.0f)); this->registerChild(this->buttonBack); _SET_CLICK_EVENT_FUNCTION(this->buttonBack, _clickScrollBack); this->buttonBar = new ImageButton(aprilui::generateName("aprilui::ScrollSkinButtonBar"), grect(0.0f, 0.0f, -1.0f, -1.0f)); this->registerChild(this->buttonBar); _SET_MOUSEDOWN_EVENT_FUNCTION(this->buttonBar, _mouseDownScrollBar); _SET_CLICK_EVENT_FUNCTION(this->buttonBar, _clickScrollBar); } this->buttonBegin->trySetImageByName(this->skinName + "/" + this->_getSkinNameBeginNormal()); this->buttonBegin->trySetHoverImageByName(this->skinName + "/" + this->_getSkinNameBeginHover()); this->buttonBegin->trySetPushedImageByName(this->skinName + "/" + this->_getSkinNameBeginPushed()); this->buttonBegin->resizeToFitImage(); this->buttonEnd->trySetImageByName(this->skinName + "/" + this->_getSkinNameEndNormal()); this->buttonEnd->trySetHoverImageByName(this->skinName + "/" + this->_getSkinNameEndHover()); this->buttonEnd->trySetPushedImageByName(this->skinName + "/" + this->_getSkinNameEndPushed()); this->buttonEnd->resizeToFitImage(); this->buttonBack->trySetImageByName(this->skinName + "/" + this->_getSkinNameBackground()); this->buttonBack->trySetHoverImageByName(this->skinName + "/" + this->_getSkinNameBackground()); this->buttonBack->trySetPushedImageByName(this->skinName + "/" + this->_getSkinNameBackground()); this->buttonBack->resizeToFitImage(); this->buttonBar->trySetImageByName(this->skinName + "/" + this->_getSkinNameBarNormal()); this->buttonBar->trySetHoverImageByName(this->skinName + "/" + this->_getSkinNameBarHover()); this->buttonBar->trySetPushedImageByName(this->skinName + "/" + this->_getSkinNameBarPushed()); this->buttonBar->resizeToFitImage(); this->_updateChildren(); this->_updateBar(); } else if (buttonBegin != NULL) { this->unregisterChild(this->buttonBegin); delete this->buttonBegin; this->buttonBegin = NULL; this->unregisterChild(this->buttonEnd); delete this->buttonEnd; this->buttonEnd = NULL; this->unregisterChild(this->buttonBack); delete this->buttonBack; this->buttonBack = NULL; this->unregisterChild(this->buttonBar); delete this->buttonBar; this->buttonBar = NULL; } } }
void QDBase::exportToPNM(void) { DEBUG_MSG("QDViewer::exportToPNM(): exporting the image into a PPM file\n"); DEBUG_MAKE_INDENT(3); // Guess on the format bool bw=getMode()==IDC_DISPLAY_BLACKWHITE; QString format_str=bw ? "PBM" : "PPM"; GUTF8String ext=bw ? ".pbm" : ".ppm"; bool raw=0; { QString mesg = tr("This will export the DjVu image in either 'Raw %1'\n" "or 'ASCII %2' format. Which one do you prefer?\n") .arg(format_str) .arg(format_str); switch(QMessageBox::information(this, tr("Exporting DjVu image..."), mesg, tr("&Raw"), tr("&Ascii"), tr("&Cancel"), 0, 2)) { case 0: raw=1; break; case 1: raw=0; break; default: return; } } static const char *filters[] = { 0, 0, 0 }; QString filter1 = tr("All files (*)"); filters[0]= ((bw) ? "*.pbm" : "*.ppm"); filters[1] = filter1; GURL file_url=dimg->get_djvu_file()->get_url(); QString save_dir=QeFileDialog::lastSaveDir; if (!QFileInfo(save_dir).isDir()) if (file_url.is_local_file_url()) while(true) { QString dir = QFileInfo(QStringFromGString( file_url.UTF8Filename())).dirPath(); if (dir) { save_dir=dir; break; } file_url=GURL::UTF8(file_url.name(),file_url.base().base()); } if (!QFileInfo(save_dir).isDir()) save_dir=QDir::currentDirPath(); GUTF8String fname=GURL::expand_name(file_url.fname(), GStringFromQString(save_dir)); QFileInfo fi=QFileInfo(QStringFromGString(fname)); fname=GStringFromQString(fi.dirPath())+"/"+GOS::basename(fname, ".djvu")+ext; QeFileDialog fd(save_dir, filters[0], this, "djvu_fd", TRUE); fd.setFilters((const char **) filters); fd.setCaption(tr("Select export file name...")); fd.setSelection(QStringFromGString(fname)); if (fd.exec()==QDialog::Accepted) { int width=dimg->get_width(); int height=dimg->get_height(); QProgressDialog progress(tr("Please stand by..."), tr("&Abort"), height, this, "progress", TRUE); progress.setMinimumWidth(progress.sizeHint().width()*3/2); progress.setCaption(tr("DjVu: Exporting image...")); progress.setMinimumDuration(0); progress.setProgress(0); static char char_to_str[256][5]; for(int i=0;i<256;i++) sprintf(char_to_str[i], "%d ", i); static short char_to_str_len[256]; for(int i=0;i<256;i++) char_to_str_len[i]=strlen(char_to_str[i]); GRect doc_grect(0, 0, width, height); GUTF8String selected=GStringFromQString(fd.selectedFile()); GP<ByteStream> gstr=ByteStream::create(GURL::Filename::UTF8(selected), "wb"); ByteStream &str=*gstr; static const char *generated="#Image generated by DjVu"; if (bw) { GUTF8String head; if (raw) head.format("P4\n%d %d\n", width, height); else head.format("P1\n%s (xdpi=%u,ypdi=%u)\n%d %d\n", generated, dimg->get_dpi(), dimg->get_dpi(), width, height); str.writall((void*)(const char *)head, head.length()); } else { GUTF8String head; if (raw) head.format("P6\n%d %d\n255\n", width, height); else head.format("P3\n%s (xdpi=%u,ydpi=%u)\n%d %d\n255\n", generated, dimg->get_dpi(), dimg->get_dpi(), width, height); str.writall((void*)(const char *)head, head.length()); } const int MAXPIXELS=100000; int band_height=MAXPIXELS/width; if (band_height>height*7/8) band_height=height; for(int band_y=height-band_height;band_height;band_y-=band_height) { GRect grect(0, band_y, width, band_height); if (bw) { GP<GBitmap> bmp=dimg->get_bitmap(grect, doc_grect); if (!bmp) G_THROW(ERR_MSG("QDBase.bitmap_not_found")); for(int n=bmp->rows()-1;n>=0;n--) { const unsigned char * row=(*bmp)[n]; if (raw) { TArray<char> buffer(bmp->columns()/8+1); char * ptr=buffer; unsigned char acc=0; unsigned char mask=0; for(u_int c=0;c<bmp->columns();c++) { if (mask==0) mask=0x80; if (row[c]) acc|=mask; mask>>=1; if (mask==0) { *ptr++=acc; acc=mask=0; } } if (mask!=0) *ptr++=acc; str.writall((const char*)buffer, ptr-buffer); } else { TArray<char> buffer(256); char * ptr=buffer; for(u_int c=0;c<bmp->columns();) { unsigned char bit=(row[c] ? '1' : '0'); *ptr++=bit; c++; if (c==bmp->columns() || (c & 0xff)==0) { *ptr++='\n'; str.writall((const char*)buffer, ptr-buffer); ptr=buffer; } } } // raw or not raw } // for(row=...) } else // not bw {
/**************************** Editing MapArea *******************************/ void MapArea::move(const GRect & doc_rect, int x, int y, int vic_code, int vic_data) { if (!mapper) return; if (vic_code>=OBJECT_CODES) { ma_move(doc_rect, x, y, vic_code, vic_data); return; } ma_copySaved(); GMapArea * copy=ma_getCopiedData(); int xmin=copy->get_xmin(), ymin=copy->get_ymin(); int xmax=copy->get_xmax(), ymax=copy->get_ymax(); GRect grect(xmin, ymin, xmax-xmin, ymax-ymin); mapper->map(grect); xmin=grect.xmin; ymin=grect.ymin; xmax=grect.xmax; ymax=grect.ymax; int width=xmax-xmin, height=ymax-ymin; int dx=x-start_x, dy=y-start_y; switch(vic_code) { case TOP_LEFT: if (dx>=width || dy>=height) return; if (xmin+dx<doc_rect.xmin) dx=doc_rect.xmin-xmin; if (ymin+dy<doc_rect.ymin) dy=doc_rect.ymin-ymin; grect.xmin+=dx; grect.ymin+=dy; mapper->unmap(grect); copy->transform(grect); break; case TOP_RIGHT: if (-dx>=width || dy>=height) return; if (xmax+dx>doc_rect.xmax) dx=doc_rect.xmax-xmax; if (ymin+dy<doc_rect.ymin) dy=doc_rect.ymin-ymin; grect.xmax+=dx; grect.ymin+=dy; mapper->unmap(grect); copy->transform(grect); break; case BOTTOM_RIGHT: if (-dx>=width || -dy>=height) return; if (xmax+dx>doc_rect.xmax) dx=doc_rect.xmax-xmax; if (ymax+dy>doc_rect.ymax) dy=doc_rect.ymax-ymax; grect.xmax+=dx; grect.ymax+=dy; mapper->unmap(grect); copy->transform(grect); break; case BOTTOM_LEFT: if (dx>=width || -dy>=height) return; if (xmin+dx<doc_rect.xmin) dx=doc_rect.xmin-xmin; if (ymax+dy>doc_rect.ymax) dy=doc_rect.ymax-ymax; grect.xmin+=dx; grect.ymax+=dy; mapper->unmap(grect); copy->transform(grect); break; case TOP: if (dy>=height) return; if (ymin+dy<doc_rect.ymin) dy=doc_rect.ymin-ymin; grect.ymin+=dy; mapper->unmap(grect); copy->transform(grect); break; case BOTTOM: if (-dy>=height) return; if (ymax+dy>doc_rect.ymax) dy=doc_rect.ymax-ymax; grect.ymax+=dy; mapper->unmap(grect); copy->transform(grect); break; case LEFT: if (dx>=width) return; if (xmin+dx<doc_rect.xmin) dx=doc_rect.xmin-xmin; grect.xmin+=dx; mapper->unmap(grect); copy->transform(grect); break; case RIGHT: if (-dx>=width) return; if (xmax+dx>doc_rect.xmax) dx=doc_rect.xmax-xmax; grect.xmax+=dx; mapper->unmap(grect); copy->transform(grect); break; case INSIDE: if (xmin+dx<doc_rect.xmin) dx=doc_rect.xmin-xmin; if (xmax+dx>doc_rect.xmax) dx=doc_rect.xmax-xmax; if (ymin+dy<doc_rect.ymin) dy=doc_rect.ymin-ymin; if (ymax+dy>doc_rect.ymax) dy=doc_rect.ymax-ymax; grect.xmin+=dx; grect.xmax+=dx; grect.ymin+=dy; grect.ymax+=dy; mapper->unmap(grect); copy->transform(grect); break; } const char *s=copy->check_object(); if (!s || !s[0]) ma_loadCopy(); }
void RenderSystem::setOrthoProjection(gvec2 size) { this->setOrthoProjection(grect(0.0f, 0.0f, size)); }
bool onUpdate(float timeDelta) { april::rendersys->clear(); april::rendersys->setOrthoProjection(drawRect); april::rendersys->setTexture(background); v[0].x = 0; v[0].y = 0; v[0].z = 0; v[0].u = 0; v[0].v = 0; v[1].x = drawRect.w; v[1].y = 0; v[1].z = 0; v[1].u = 1; v[1].v = 0; v[2].x = 0; v[2].y = drawRect.h; v[2].z = 0; v[2].u = 0; v[2].v = 1; v[3].x = drawRect.w; v[3].y = drawRect.h; v[3].z = 0; v[3].u = 1; v[3].v = 1; april::rendersys->render(april::RO_TRIANGLE_STRIP, v, 4); april::rendersys->setTexture(NULL); april::rendersys->drawFilledRect(grect(size.x, 0, 10, drawRect.h), april::Color::Magenta); april::rendersys->drawFilledRect(grect(size.x * 2 + 10, 0, 10, drawRect.h), april::Color::Magenta); april::rendersys->drawFilledRect(grect(0, size.y, drawRect.w, 10), april::Color::Magenta); april::rendersys->drawFilledRect(grect(0, size.y * 2 + 10, drawRect.w, 10), april::Color::Magenta); for (int j = 0; j < 3; j++) { for (int i = 0; i < 3; i++) { if (positions[i][j] == 1) { draw_symbol(i + 1, j + 1, "x_symbol"); } else if (positions[i][j] == 2) { draw_symbol(i + 1, j + 1, "o_symbol"); } } } switch (victory) { case 1: draw_line(0, 0, 0, 2, "line_horz"); break; case 2: draw_line(1, 0, 1, 2, "line_horz"); break; case 3: draw_line(2, 0, 2, 2, "line_horz"); break; case 4: draw_line(0, 0, 2, 0, "line_vert"); break; case 5: draw_line(0, 1, 2, 1, "line_vert"); break; case 6: draw_line(0, 2, 2, 2, "line_vert"); break; case 7: draw_line(0, 0, 2, 2, "line45"); break; case 8: draw_line(0, 0, 2, 2, "line315"); break; } return true; }
void ScrollBar::notifyEvent(chstr name, void* params) { Object::notifyEvent(name, params); if (name == "AttachToObject") { Container* parent = dynamic_cast<Container*>(this->parent); if (parent == NULL) { hlog::warnf(aprilui::logTag, "ScrollBar '%s' not attached to object of class Container!", this->name.c_str()); } } else if (name == "SkinChange") { if (this->skinName != "") { if (this->_buttonBackgroundSkinned == NULL) { this->_buttonBackgroundSkinned = new ScrollBarButtonBackground(april::generateName("aprilui::ScrollButtonBackground"), grect(0.0f, 0.0f, -1.0f, -1.0f)); this->registerChild(this->_buttonBackgroundSkinned); } if (this->_buttonSliderSkinned == NULL) { this->_buttonSliderSkinned = new ScrollBarButtonSlider(april::generateName("aprilui::ScrollButtonSlider"), grect(0.0f, 0.0f, -1.0f, -1.0f)); this->registerChild(this->_buttonSliderSkinned); } if (this->_buttonForwardSkinned == NULL) { this->_buttonForwardSkinned = new ScrollBarButtonForward(april::generateName("aprilui::ScrollButtonForward"), grect(0.0f, 0.0f, -1.0f, -1.0f)); this->registerChild(this->_buttonForwardSkinned); } if (this->_buttonBackwardSkinned == NULL) { this->_buttonBackwardSkinned = new ScrollBarButtonBackward(april::generateName("aprilui::ScrollButtonBackward"), grect(0.0f, 0.0f, -1.0f, -1.0f)); this->registerChild(this->_buttonBackwardSkinned); } this->_buttonBackgroundSkinned->trySetImageByName(this->skinName + "/" + this->_getSkinNameBackground()); this->_buttonBackgroundSkinned->trySetHoverImageByName(this->skinName + "/" + this->_getSkinNameBackground()); this->_buttonBackgroundSkinned->trySetPushedImageByName(this->skinName + "/" + this->_getSkinNameBackground()); this->_buttonBackgroundSkinned->resizeToFitImage(); this->_buttonBackgroundSkinned->setVisible(this->_buttonBackground == NULL); this->_buttonSliderSkinned->trySetImageByName(this->skinName + "/" + this->_getSkinNameSliderNormal()); this->_buttonSliderSkinned->trySetHoverImageByName(this->skinName + "/" + this->_getSkinNameSliderHover()); this->_buttonSliderSkinned->trySetPushedImageByName(this->skinName + "/" + this->_getSkinNameSliderPushed()); this->_buttonSliderSkinned->resizeToFitImage(); this->_buttonSliderSkinned->setVisible(this->_buttonSlider == NULL); this->_buttonForwardSkinned->trySetImageByName(this->skinName + "/" + this->_getSkinNameForwardNormal()); this->_buttonForwardSkinned->trySetHoverImageByName(this->skinName + "/" + this->_getSkinNameForwardHover()); this->_buttonForwardSkinned->trySetPushedImageByName(this->skinName + "/" + this->_getSkinNameForwardPushed()); this->_buttonForwardSkinned->resizeToFitImage(); this->_buttonForwardSkinned->setVisible(this->_buttonForward == NULL); this->_buttonBackwardSkinned->trySetImageByName(this->skinName + "/" + this->_getSkinNameBackwardNormal()); this->_buttonBackwardSkinned->trySetHoverImageByName(this->skinName + "/" + this->_getSkinNameBackwardHover()); this->_buttonBackwardSkinned->trySetPushedImageByName(this->skinName + "/" + this->_getSkinNameBackwardPushed()); this->_buttonBackwardSkinned->resizeToFitImage(); this->_buttonBackwardSkinned->setVisible(this->_buttonBackward == NULL); this->_updateChildren(); this->_updateBar(); } else { if (this->_buttonBackgroundSkinned != NULL) { this->unregisterChild(this->_buttonBackgroundSkinned); delete this->_buttonBackgroundSkinned; this->_buttonBackgroundSkinned = NULL; } if (this->_buttonSliderSkinned != NULL) { this->unregisterChild(this->_buttonSliderSkinned); delete this->_buttonSliderSkinned; this->_buttonSliderSkinned = NULL; } if (this->_buttonForwardSkinned != NULL) { this->unregisterChild(this->_buttonForwardSkinned); delete this->_buttonForwardSkinned; this->_buttonForwardSkinned = NULL; } if (this->_buttonBackwardSkinned != NULL) { this->unregisterChild(this->_buttonBackwardSkinned); delete this->_buttonBackwardSkinned; this->_buttonBackwardSkinned = NULL; } } } }
void VideoObject::_createClip(bool waitForCache) { hstr path = getFullPath(); april::Image::Format textureFormat = _getTextureFormat(); destroyResources(); if (path.endsWith(".mp4")) { hstr archive = hresource::getArchive(); if (archive != "") { path = hrdir::joinPath(archive, path); } } try { TheoraOutputMode mode = TH_RGBA; if (textureFormat == april::Image::FORMAT_RGBA) mode = TH_RGBA; else if (textureFormat == april::Image::FORMAT_RGBX) mode = TH_RGBX; else if (textureFormat == april::Image::FORMAT_BGRA) mode = TH_BGRA; else if (textureFormat == april::Image::FORMAT_BGRX) mode = TH_BGRX; else if (textureFormat == april::Image::FORMAT_ARGB) mode = TH_ARGB; else if (textureFormat == april::Image::FORMAT_XRGB) mode = TH_XRGB; else if (textureFormat == april::Image::FORMAT_ABGR) mode = TH_ABGR; else if (textureFormat == april::Image::FORMAT_XBGR) mode = TH_XBGR; else if (textureFormat == april::Image::FORMAT_RGB) mode = TH_RGBX; else if (textureFormat == april::Image::FORMAT_BGR) mode = TH_BGRX; else if (textureFormat == april::Image::FORMAT_GRAYSCALE) mode = TH_GREY; int ram = april::getSystemInfo().ram; int precached = 16; #if defined(_ANDROID) || defined(_WINRT) && !defined(_WINP8) // Android and WinRT libtheoraplayer uses an optimized libtheora which is faster, but still slower than // a native hardware accelerated codec. So (for now) we use a larger precache to counter it. Though, WinP8 can't handle this memory-wise. if (ram > 512) precached = 32; #else if (ram < 384) precached = 6; else if (ram < 512) precached = 8; else if (ram < 1024) { if (path.contains("lowres")) precached = 16; else precached = 8; } #endif if (path.endsWith("mp4")) { try { if (april::window->getName() == "OpenKODE") // because mp4's are opened via apple's api, and that doesn't play nice with OpenKODE dir structure. mClip = gVideoManager->createVideoClip(hrdir::joinPath("res", path).cStr(), mode, precached); else mClip = gVideoManager->createVideoClip(path.cStr(), mode, precached); } catch (_TheoraGenericException& e) { // pass the exception further as a hexception so the general system can understand it throw Exception(e.getErrorText().c_str()); } } else { if (!path.endsWith(".mp4") && ram > 256) { hresource r; r.open(path); unsigned long size = (unsigned long) r.size(); TheoraDataSource* source; // additional performance optimization: preload file in RAM to speed up decoding, every bit counts on Android/WinRT ARM // but only for "reasonably" sized files if (size < 64 * 1024 * 1024) { hlog::write(logTag, "Preloading video file to memory: " + path); unsigned char* data = new unsigned char[size]; r.readRaw(data, (int) size); source = new TheoraMemoryFileDataSource(data, size, path.cStr()); } else { source = new AprilVideoDataSource(path); } mClip = gVideoManager->createVideoClip(source, mode, precached); r.close(); hlog::write(logTag, "Created video clip."); } else { mClip = gVideoManager->createVideoClip(new AprilVideoDataSource(path), mode, precached); } } } catch (_TheoraGenericException& e) { throw Exception(e.getErrorText().c_str()); } if (mClip->getWidth() == 0) throw Exception("Failed to load video file: " + path); mClip->setAutoRestart(mLoop); int tw = mClip->getWidth(); int th = mClip->getHeight(); april::RenderSystem::Caps caps = april::rendersys->getCaps(); if (!caps.npotTexturesLimited && !caps.npotTextures) { tw = hpotceil(tw); th = hpotceil(th); } hlog::write(logTag, "Creating video textures for " + mClipName); april::Texture* tex; for (int i = 0; i < 2; i++) { tex = april::rendersys->createTexture(tw, th, april::Color::Clear, textureFormat, april::Texture::TYPE_VOLATILE); tex->setAddressMode(april::Texture::ADDRESS_CLAMP); mTexture = new aprilui::Texture(tex->getFilename() + "_" + hstr(i + 1), tex); mVideoImage = new aprilui::Image(mTexture, "video_img_" + hstr(i + 1), grect(mClip->getSubFrameOffsetX(), mClip->getSubFrameOffsetY(), mClip->getSubFrameWidth(), mClip->getSubFrameHeight())); mVideoImage->setBlendMode(mBlendMode); mTextures += mTexture; mVideoImages += mVideoImage; } if (waitForCache && mInitialPrecacheFactor > 0.0f) { float factor = hmax(2.0f / mClip->getNumPrecachedFrames(), mInitialPrecacheFactor); float precached = (float) mClip->getNumReadyFrames() / mClip->getNumPrecachedFrames(); if (precached < factor) { hlog::writef(logTag, "Waiting for cache (%.1f%% / %.1f%%): %s", precached * 100.0f, factor * 100.0f, path.cStr()); if (factor > 0) { precached = mClip->waitForCache(factor, mInitialPrecacheTimeout); // better to wait a while then to display an empty image } if (precached < factor) { hlog::writef(logTag, "Initial precache cached %.1f%% frames, target precache factor was %.1f%%", precached * 100.0f, factor * 100.0f); } } } if (mAudioName != "") { hstr category = "video"; if (mAudioName.contains("/")) { harray<hstr> folders = hrdir::splitPath(mAudioName); hstr path_category = folders[folders.size() - 2]; if (xal::manager->hasCategory(path_category)) category = path_category; } if (category == "video" && !xal::manager->hasCategory("video")) { #if defined(_WINRT) || defined(_ANDROID) xal::manager->createCategory("video", xal::ON_DEMAND, xal::DISK); #else if (april::getSystemInfo().ram >= 512) { xal::manager->createCategory("video", xal::STREAMED, xal::RAM); } else { xal::manager->createCategory("video", xal::STREAMED, xal::DISK); } #endif } mSound = xal::manager->createSound(hrdir::joinPath(hrdir::joinPath(this->dataset->getFilePath(), "video"), mAudioName), category); if (mSound != NULL) { mAudioPlayer = xal::manager->createPlayer(mSound->getName()); mTimer = new AudioVideoTimer(this, mAudioPlayer, mAudioSyncOffset); } } if (mTimer == NULL) { mTimer = new VideoTimer(this); } mClip->setTimer(mTimer); mClip->setPlaybackSpeed(mSpeed); update(0); // to grab the first frame. }