TEST(File, SeveralSizes) { she::ScopedHandle<she::System> system(she::CreateSystem()); // Register all possible image formats. FileFormatsManager::instance().registerAllFormats(); std::vector<char> fn(256); for (int w=10; w<=10+503*2; w+=503) { for (int h=10; h<=10+503*2; h+=503) { //std::sprintf(&fn[0], "test_%dx%d.ase", w, h); std::sprintf(&fn[0], "test.ase"); { UniquePtr<Document> doc(Document::createBasicDocument(IMAGE_INDEXED, w, h, 256)); doc->setFilename(&fn[0]); // Random pixels LayerImage* layer = dynamic_cast<LayerImage*>(doc->getSprite()->getFolder()->getFirstLayer()); ASSERT_TRUE(layer != NULL); Image* image = doc->getSprite()->getStock()->getImage(layer->getCel(FrameNumber(0))->getImage()); std::srand(w*h); int c = std::rand()%256; for (int y=0; y<h; y++) { for (int x=0; x<w; x++) { image_putpixel_fast<IndexedTraits>(image, x, y, c); if ((std::rand()&4) == 0) c = std::rand()%256; } } save_document(doc); } { UniquePtr<Document> doc(load_document(&fn[0])); ASSERT_EQ(w, doc->getSprite()->getWidth()); ASSERT_EQ(h, doc->getSprite()->getHeight()); // Same random pixels (see the seed) LayerImage* layer = dynamic_cast<LayerImage*>(doc->getSprite()->getFolder()->getFirstLayer()); ASSERT_TRUE(layer != NULL); Image* image = doc->getSprite()->getStock()->getImage(layer->getCel(FrameNumber(0))->getImage()); std::srand(w*h); int c = std::rand()%256; for (int y=0; y<h; y++) { for (int x=0; x<w; x++) { ASSERT_EQ(c, image_getpixel_fast<IndexedTraits>(image, x, y)); if ((std::rand()&4) == 0) c = std::rand()%256; } } } } } }
Document* Document::createBasicDocument(PixelFormat format, int width, int height, int ncolors) { // Create the sprite. UniquePtr<Sprite> sprite(new Sprite(format, width, height, ncolors)); sprite->setTotalFrames(FrameNumber(1)); // Create the main image. int indexInStock; { UniquePtr<Image> image(Image::create(format, width, height)); // Clear the image with mask color. image_clear(image, 0); // Add image in the sprite's stock. indexInStock = sprite->getStock()->addImage(image); image.release(); // Release the image because it is in the sprite's stock. } // Create the first transparent layer. { UniquePtr<LayerImage> layer(new LayerImage(sprite)); layer->setName("Layer 1"); // Create the cel. { UniquePtr<Cel> cel(new Cel(FrameNumber(0), indexInStock)); cel->setPosition(0, 0); // Add the cel in the layer. layer->addCel(cel); cel.release(); // Release the cel because it is in the layer } // Add the layer in the sprite. sprite->getFolder()->addLayer(layer.release()); // Release the layer because it's owned by the sprite } // Create the document with the new sprite. UniquePtr<Document> document(new Document(sprite)); sprite.release(); // Release the sprite because it is in the document. document->setFilename("Sprite"); return document.release(); // Release the document (it does not throw) returning the raw pointer }
raster::FrameNumber calculate_next_frame( raster::Sprite* sprite, raster::FrameNumber frame, IDocumentSettings* docSettings, bool& pingPongForward) { FrameNumber first = FrameNumber(0); FrameNumber last = sprite->getLastFrame(); if (docSettings->getLoopAnimation()) { FrameNumber loopBegin, loopEnd; docSettings->getLoopRange(&loopBegin, &loopEnd); if (loopBegin < first) loopBegin = first; if (loopEnd > last) loopEnd = last; first = loopBegin; last = loopEnd; } switch (docSettings->getAnimationDirection()) { case IDocumentSettings::AniDir_Normal: frame = frame.next(); if (frame > last) frame = first; break; case IDocumentSettings::AniDir_Reverse: frame = frame.previous(); if (frame < first) frame = last; break; case IDocumentSettings::AniDir_PingPong: if (pingPongForward) { frame = frame.next(); if (frame > last) { frame = last.previous(); if (frame < first) frame = first; pingPongForward = false; } } else { frame = frame.previous(); if (frame < first) { frame = first.next(); if (frame > last) frame = last; pingPongForward = true; } } break; } return frame; }
void Sprite::setTotalFrames(FrameNumber frames) { frames = MAX(FrameNumber(1), frames); m_frlens.resize(frames); if (frames > m_frames) { for (FrameNumber c=m_frames; c<frames; ++c) m_frlens[c] = m_frlens[m_frames.previous()]; } m_frames = frames; }
Sprite::Sprite(PixelFormat format, int width, int height, int ncolors) : Object(OBJECT_SPRITE) , m_format(format) , m_width(width) , m_height(height) , m_frames(1) { ASSERT(width > 0 && height > 0); m_frlens.push_back(100); // First frame with 100 msecs of duration m_stock = new Stock(format); m_folder = new LayerFolder(this); // Generate palette Palette pal(FrameNumber(0), ncolors); switch (format) { // For colored images case IMAGE_RGB: case IMAGE_INDEXED: pal.resize(ncolors); break; // For black and white images case IMAGE_GRAYSCALE: case IMAGE_BITMAP: for (int c=0; c<ncolors; c++) { int g = 255 * c / (ncolors-1); g = MID(0, g, 255); pal.setEntry(c, rgba(g, g, g, 255)); } break; } // Initial RGB map m_rgbMap = NULL; // The transparent color for indexed images is 0 by default m_transparentColor = 0; setPalette(&pal, true); }
void Document::prepareExtraCel(int x, int y, int w, int h, int opacity) { ASSERT(getSprite() != NULL); if (!m_extraCel) m_extraCel = new Cel(FrameNumber(0), 0); // Ignored fields for this cell (frame, and image index) m_extraCel->setPosition(x, y); m_extraCel->setOpacity(opacity); if (!m_extraImage || m_extraImage->getPixelFormat() != getSprite()->getPixelFormat() || m_extraImage->w != w || m_extraImage->h != h) { delete m_extraImage; // image m_extraImage = Image::create(getSprite()->getPixelFormat(), w, h); image_clear(m_extraImage, m_extraImage->mask_color = 0); } }
#include "raster/stock.h" #include "undo_transaction.h" #include "undoers/add_cel.h" #include "undoers/add_image.h" #include "undoers/remove_cel.h" #include "undoers/remove_image.h" #include "undoers/replace_image.h" #include "undoers/set_cel_frame.h" #include "undoers/set_cel_opacity.h" #include "undoers/set_cel_position.h" // These variables indicate what cel to move (and the sprite's frame // indicates where to move it). static Layer* src_layer = NULL; // TODO warning not thread safe static Layer* dst_layer = NULL; static FrameNumber src_frame = FrameNumber(0); static FrameNumber dst_frame = FrameNumber(0); static void remove_cel(Sprite* sprite, UndoTransaction& undo, LayerImage* layer, Cel* cel); void set_frame_to_handle(Layer* _src_layer, FrameNumber _src_frame, Layer* _dst_layer, FrameNumber _dst_frame) { src_layer = _src_layer; src_frame = _src_frame; dst_layer = _dst_layer; dst_frame = _dst_frame; } void move_cel(ContextWriter& writer) {
void set_black_palette() { Palette* p = new Palette(FrameNumber(0), 256); set_current_palette(p, true); delete p; }
namespace app { // These variables indicate what cel to move (and the sprite's frame // indicates where to move it). static Layer* src_layer = NULL; // TODO warning not thread safe static Layer* dst_layer = NULL; static FrameNumber src_frame = FrameNumber(0); static FrameNumber dst_frame = FrameNumber(0); static void remove_cel(Sprite* sprite, UndoTransaction& undo, LayerImage* layer, Cel* cel); void set_frame_to_handle(Layer* _src_layer, FrameNumber _src_frame, Layer* _dst_layer, FrameNumber _dst_frame) { src_layer = _src_layer; src_frame = _src_frame; dst_layer = _dst_layer; dst_frame = _dst_frame; } void move_cel(ContextWriter& writer) { Document* document = writer.document(); Sprite* sprite = writer.sprite(); Cel *src_cel, *dst_cel; ASSERT(src_layer != NULL); ASSERT(dst_layer != NULL); ASSERT(src_frame >= 0 && src_frame < sprite->getTotalFrames()); ASSERT(dst_frame >= 0 && dst_frame < sprite->getTotalFrames()); if (src_layer->isBackground()) { copy_cel(writer); return; } src_cel = static_cast<LayerImage*>(src_layer)->getCel(src_frame); dst_cel = static_cast<LayerImage*>(dst_layer)->getCel(dst_frame); UndoTransaction undo(writer.context(), "Move Cel", undo::ModifyDocument); /* remove the 'dst_cel' (if it exists) because it must be replaced with 'src_cel' */ if ((dst_cel != NULL) && (!dst_layer->isBackground() || src_cel != NULL)) remove_cel(sprite, undo, static_cast<LayerImage*>(dst_layer), dst_cel); /* move the cel in the same layer */ if (src_cel != NULL) { if (src_layer == dst_layer) { if (undo.isEnabled()) undo.pushUndoer(new undoers::SetCelFrame(undo.getObjects(), src_cel)); src_cel->setFrame(dst_frame); } /* move the cel in different layers */ else { if (undo.isEnabled()) undo.pushUndoer(new undoers::RemoveCel(undo.getObjects(), src_layer, src_cel)); static_cast<LayerImage*>(src_layer)->removeCel(src_cel); src_cel->setFrame(dst_frame); /* if we are moving a cel from a transparent layer to the background layer, we have to clear the background of the image */ if (!src_layer->isBackground() && dst_layer->isBackground()) { Image* src_image = sprite->getStock()->getImage(src_cel->getImage()); Image* dst_image = crop_image(src_image, -src_cel->getX(), -src_cel->getY(), sprite->getWidth(), sprite->getHeight(), 0); if (undo.isEnabled()) { undo.pushUndoer(new undoers::ReplaceImage(undo.getObjects(), sprite->getStock(), src_cel->getImage())); undo.pushUndoer(new undoers::SetCelPosition(undo.getObjects(), src_cel)); undo.pushUndoer(new undoers::SetCelOpacity(undo.getObjects(), src_cel)); } clear_image(dst_image, app_get_color_to_clear_layer(dst_layer)); composite_image(dst_image, src_image, src_cel->getX(), src_cel->getY(), 255, BLEND_MODE_NORMAL); src_cel->setPosition(0, 0); src_cel->setOpacity(255); sprite->getStock()->replaceImage(src_cel->getImage(), dst_image); delete src_image; } if (undo.isEnabled()) undo.pushUndoer(new undoers::AddCel(undo.getObjects(), dst_layer, src_cel)); static_cast<LayerImage*>(dst_layer)->addCel(src_cel); } } undo.commit(); document->notifyCelMoved(src_layer, src_frame, dst_layer, dst_frame); set_frame_to_handle(NULL, FrameNumber(0), NULL, FrameNumber(0)); } void copy_cel(ContextWriter& writer) { Document* document = writer.document(); Sprite* sprite = writer.sprite(); UndoTransaction undo(writer.context(), "Move Cel", undo::ModifyDocument); Cel *src_cel, *dst_cel; ASSERT(src_layer != NULL); ASSERT(dst_layer != NULL); ASSERT(src_frame >= 0 && src_frame < sprite->getTotalFrames()); ASSERT(dst_frame >= 0 && dst_frame < sprite->getTotalFrames()); src_cel = static_cast<LayerImage*>(src_layer)->getCel(src_frame); dst_cel = static_cast<LayerImage*>(dst_layer)->getCel(dst_frame); // Remove the 'dst_cel' (if it exists) because it must be replaced // with 'src_cel' if ((dst_cel != NULL) && (!dst_layer->isBackground() || src_cel != NULL)) remove_cel(sprite, undo, static_cast<LayerImage*>(dst_layer), dst_cel); // Move the cel in the same layer. if (src_cel != NULL) { Image *src_image = sprite->getStock()->getImage(src_cel->getImage()); Image *dst_image; int image_index; int dst_cel_x; int dst_cel_y; int dst_cel_opacity; // If we are moving a cel from a transparent layer to the // background layer, we have to clear the background of the image. if (!src_layer->isBackground() && dst_layer->isBackground()) { dst_image = crop_image(src_image, -src_cel->getX(), -src_cel->getY(), sprite->getWidth(), sprite->getHeight(), 0); clear_image(dst_image, app_get_color_to_clear_layer(dst_layer)); composite_image(dst_image, src_image, src_cel->getX(), src_cel->getY(), 255, BLEND_MODE_NORMAL); dst_cel_x = 0; dst_cel_y = 0; dst_cel_opacity = 255; } else { dst_image = Image::createCopy(src_image); dst_cel_x = src_cel->getX(); dst_cel_y = src_cel->getY(); dst_cel_opacity = src_cel->getOpacity(); } // Add the image in the stock image_index = sprite->getStock()->addImage(dst_image); if (undo.isEnabled()) undo.pushUndoer(new undoers::AddImage(undo.getObjects(), sprite->getStock(), image_index)); // Create the new cel dst_cel = new Cel(dst_frame, image_index); dst_cel->setPosition(dst_cel_x, dst_cel_y); dst_cel->setOpacity(dst_cel_opacity); if (undo.isEnabled()) undo.pushUndoer(new undoers::AddCel(undo.getObjects(), dst_layer, dst_cel)); static_cast<LayerImage*>(dst_layer)->addCel(dst_cel); } undo.commit(); document->notifyCelCopied(src_layer, src_frame, dst_layer, dst_frame); set_frame_to_handle(NULL, FrameNumber(0), NULL, FrameNumber(0)); } static void remove_cel(Sprite* sprite, UndoTransaction& undo, LayerImage *layer, Cel *cel) { Image *image; Cel *it; bool used; if (sprite != NULL && layer->isImage() && cel != NULL) { /* find if the image that use the cel to remove, is used by another cels */ used = false; for (FrameNumber frame(0); frame<sprite->getTotalFrames(); ++frame) { it = layer->getCel(frame); if (it != NULL && it != cel && it->getImage() == cel->getImage()) { used = true; break; } } if (!used) { // If the image is only used by this cel, we can remove the // image from the stock. image = sprite->getStock()->getImage(cel->getImage()); if (undo.isEnabled()) undo.pushUndoer(new undoers::RemoveImage(undo.getObjects(), sprite->getStock(), cel->getImage())); sprite->getStock()->removeImage(image); delete image; } if (undo.isEnabled()) { undo.pushUndoer(new undoers::RemoveCel(undo.getObjects(), layer, cel)); } // Remove the cel layer->removeCel(cel); delete cel; } } } // namespace app
bool FliFormat::onLoad(FileOp* fop) { #define SETPAL() \ do { \ for (c=0; c<256; c++) { \ pal->setEntry(c, _rgba(cmap[c*3], \ cmap[c*3+1], \ cmap[c*3+2], 255)); \ } \ pal->setFrame(frpos_out); \ sprite->setPalette(pal, true); \ } while (0) unsigned char cmap[768]; unsigned char omap[768]; s_fli_header fli_header; Image *bmp, *old, *image; Sprite *sprite; LayerImage *layer; Palette *pal; int c, w, h; FrameNumber frpos_in; FrameNumber frpos_out; int index = 0; Cel *cel; /* open the file to read in binary mode */ FileHandle f(fop->filename.c_str(), "rb"); fli_read_header(f, &fli_header); fseek(f, 128, SEEK_SET); if (fli_header.magic == NO_HEADER) { fop_error(fop, "The file doesn't have a FLIC header\n"); return false; } /* size by frame */ w = fli_header.width; h = fli_header.height; /* create the bitmaps */ bmp = Image::create(IMAGE_INDEXED, w, h); old = Image::create(IMAGE_INDEXED, w, h); pal = new Palette(FrameNumber(0), 256); if (!bmp || !old || !pal) { fop_error(fop, "Not enough memory.\n"); if (bmp) image_free(bmp); if (old) image_free(old); if (pal) delete pal; return false; } // Create the image sprite = new Sprite(IMAGE_INDEXED, w, h, 256); layer = new LayerImage(sprite); sprite->getFolder()->addLayer(layer); layer->configureAsBackground(); // Set frames and speed sprite->setTotalFrames(FrameNumber(fli_header.frames)); sprite->setDurationForAllFrames(fli_header.speed); /* write frame by frame */ for (frpos_in = frpos_out = FrameNumber(0); frpos_in < sprite->getTotalFrames(); ++frpos_in) { /* read the frame */ fli_read_frame(f, &fli_header, (unsigned char *)old->dat, omap, (unsigned char *)bmp->dat, cmap); /* first frame, or the frames changes, or the palette changes */ if ((frpos_in == 0) || (image_count_diff(old, bmp)) #ifndef USE_LINK /* TODO this should be configurable through a check-box */ || (memcmp(omap, cmap, 768) != 0) #endif ) { /* the image changes? */ if (frpos_in != 0) ++frpos_out; /* add the new frame */ image = Image::createCopy(bmp); if (!image) { fop_error(fop, "Not enough memory\n"); break; } index = sprite->getStock()->addImage(image); if (index < 0) { image_free(image); fop_error(fop, "Not enough memory\n"); break; } cel = new Cel(frpos_out, index); layer->addCel(cel); /* first frame or the palette changes */ if ((frpos_in == 0) || (memcmp(omap, cmap, 768) != 0)) SETPAL(); } #ifdef USE_LINK /* the palette changes */ else if (memcmp(omap, cmap, 768) != 0) { ++frpos_out; SETPAL(); // Add link cel = new Cel(frpos_out, index); layer_add_cel(layer, cel); } #endif // The palette and the image don't change: add duration to the last added frame else { sprite->setFrameDuration(frpos_out, sprite->getFrameDuration(frpos_out)+fli_header.speed); } /* update the old image and color-map to the new ones to compare later */ image_copy(old, bmp, 0, 0); memcpy(omap, cmap, 768); /* update progress */ fop_progress(fop, (float)(frpos_in+1) / (float)(sprite->getTotalFrames())); if (fop_is_stop(fop)) break; /* just one frame? */ if (fop->oneframe) break; } // Update number of frames sprite->setTotalFrames(frpos_out.next()); // Destroy the bitmaps image_free(bmp); image_free(old); delete pal; fop->document = new Document(sprite); return true; }
void KernelStart(char *cmd_args[], unsigned int pmem_size, UserContext *uctxt) { //mark the initial KernelBrk KernelBrk = KernelDataEnd; //FreeFrameCount is only used page_table.c FreeFrameCount = pmem_size / PAGESIZE; ipc_table = (ObjectNode **) malloc(sizeof(ObjectNode *) * HASH_LEN); if (NULL == ipc_table) { TracePrintf(0, "ipc_table cannot be initialized!\n"); return; } memset(ipc_table, 0, sizeof(ObjectNode *) * HASH_LEN); ReadyQueue = (Queue *) malloc(sizeof(Queue)); DelayQueue = (Queue *) malloc(sizeof(Queue)); if (NULL == ReadyQueue) { TracePrintf(0, "ReadyQueue cannot be initialized!\n"); return; } if (NULL == DelayQueue) { TracePrintf(0, "DelayQueue cannot be initialized!\n"); return; } memset(ReadyQueue, 0, sizeof(Queue)); memset(DelayQueue, 0, sizeof(Queue)); u_int i; for (i = 0; i < NUM_TERMINALS; i++) { BufferQueue[i] = (Queue *) malloc(sizeof(Queue)); ReceiveQueue[i] = (Queue *) malloc(sizeof(Queue)); TransmitQueue[i] = (Queue *) malloc(sizeof(Queue)); if (NULL == BufferQueue[i]) { TracePrintf(0, "BufferQueue[%d] cannot be initialized!\n", i); return; } if (NULL == ReceiveQueue[i]) { TracePrintf(0, "ReceiveQueue[%d] cannot be initialized!\n", i); return; } if (NULL == TransmitQueue[i]) { TracePrintf(0, "TransmitQueue[%d] cannot be initialized!\n", i); return; } memset(BufferQueue[i], 0, sizeof(Queue)); memset(ReceiveQueue[i], 0, sizeof(Queue)); memset(TransmitQueue[i], 0, sizeof(Queue)); } //create interrupt vector table in kernel void **interruptVectorTable = (void **) malloc(sizeof(void *) * TRAP_VECTOR_SIZE); if (NULL == interruptVectorTable) { TracePrintf(0, "Interrupt Vector Table cannot be initialized!\n"); return; } //fill each entry in table with pointer to correct handler interruptVectorTable[TRAP_KERNEL] = &TrapKernelHandler; interruptVectorTable[TRAP_CLOCK] = &TrapClockHandler; interruptVectorTable[TRAP_ILLEGAL] = &TrapIllegalHandler; interruptVectorTable[TRAP_MEMORY] = &TrapMemoryHandler; interruptVectorTable[TRAP_MATH] = &TrapMathHandler; interruptVectorTable[TRAP_TTY_RECEIVE] = &TrapTtyReceiveHandler; interruptVectorTable[TRAP_TTY_TRANSMIT] = &TrapTtyTransmitHandler; interruptVectorTable[TRAP_DISK] = &TrapDiskHandler; for (i = 8; i < 16; i++) { interruptVectorTable[i] = &TrapErrorHandler; } //point REG_VECTOR_BASE to interrupt vector table WriteRegister(REG_VECTOR_BASE, (u_int) interruptVectorTable); TracePrintf(0, "Interrupt vector table initialization completed.\n"); //Build page table for Region 0 KernelPageTable = (PTE *) malloc(sizeof(PTE) * MAX_PT_LEN); if (NULL == KernelPageTable) { TracePrintf(0, "KernelPageTable cannot be initialized!\n"); return; } memset(KernelPageTable, 0, sizeof(PTE) * MAX_PT_LEN); TracePrintf(0, "Page tables built successfully.\n"); //create kernel stack union KS = (KernelStack *) KERNEL_STACK_BASE; TracePrintf(0, "Kernel stack initialization completed.\n"); //build input init process PCB KS->CurrentPCB = InitPCB = InitializePCB(); if (NULL == InitPCB) { TracePrintf(0, "InitPCB cannot be initialized!\n"); return; } // We enablePTE after using all the malloc in the kernel because // only in this way we can make sure the getFreeFrame will be called // and update the FreeFrameCount. enablePTE(0, Page(KernelDataStart), PROT_READ | PROT_EXEC); enablePTE(Page(KernelDataStart), Page(KernelBrk), PROT_READ | PROT_WRITE); enablePTE(INTERFACE, Page(KERNEL_STACK_LIMIT), PROT_READ | PROT_WRITE); // initialize virtual memory registers WriteRegister(REG_PTBR0, (u_int) KernelPageTable); WriteRegister(REG_PTLR0, MAX_PT_LEN); WriteRegister(REG_PTBR1, (u_int) KS->CurrentPCB->pagetable); WriteRegister(REG_PTLR1, MAX_PT_LEN); TracePrintf(0, "Table information loading to hardware completed.\n"); //set up the link list to keep track of free frames //from KernelBrk to KERNEL_STACK_BASE *FrameNumber(INTERFACE) = Page(KernelBrk); for (i = Page(KernelBrk); i < INTERFACE - 1; i++) { *FrameNumber(i) = i + 1; } *FrameNumber(INTERFACE - 1) = Page(VMEM_0_LIMIT); for (i = Page(VMEM_0_LIMIT); i < Page(pmem_size - 1); i++) { *FrameNumber(i) = i + 1; } TracePrintf(0, "Free frames' linked list has been set up.\n"); //enable virtual memory WriteRegister(REG_VM_ENABLE, 1); VM_ENABLED = 1; TracePrintf(0, "Virtual memory has been enabled.\n"); TracePrintf(0, "Load input program. (Default init)\n"); if (NULL != cmd_args[0]) { if (FAILURE == LoadProgram(cmd_args[0], cmd_args, InitPCB)) { TracePrintf(0, "Load input program failed!\n"); return; } } else { char *args[] = {"init", NULL}; if (FAILURE == LoadProgram(args[0], args, InitPCB)) { TracePrintf(0, "Load input program failed!\n"); return; } } TracePrintf(0, "Build the Idle process.\n"); //build kernel idle process PCB IdlePCB = InitializePCB(); if (NULL == IdlePCB) { TracePrintf(0, "IdlePCB cannot be initialized!\n"); return; } //sp = virtual address of top of stack IdlePCB->uctxt.sp = (void *) (VMEM_1_LIMIT - INITIAL_STACK_FRAME_SIZE - POST_ARGV_NULL_SPACE); //pc = virtual address of DoIdle function IdlePCB->uctxt.pc = &DoIdle; //enable user stack for idle process IdlePCB->pagetable[MAX_PT_LEN - 1].valid = 1; IdlePCB->pagetable[MAX_PT_LEN - 1].prot = PROT_READ | PROT_WRITE; if (0 == FreeFrameCount) { TracePrintf(0, "No frame for Idle process pagetable!\n"); return; } IdlePCB->pagetable[MAX_PT_LEN - 1].pfn = getFreeFrame(0); //use MyKCS initialize IdlePCB's KC and KS KernelContextSwitch(KCKSInit, (void *) IdlePCB, NULL); TracePrintf(0, "How many time will this line be printed?\n"); //copy current context into hardware provided context *uctxt = KS->CurrentPCB->uctxt; TracePrintf(0, "KernelStart finished.\n"); }
/* loads a COL file (Animator and Animator Pro format) */ Palette *load_col_file(const char *filename) { #if (MAKE_VERSION(4, 2, 1) >= MAKE_VERSION(ALLEGRO_VERSION, \ ALLEGRO_SUB_VERSION, \ ALLEGRO_WIP_VERSION)) int size = file_size(filename); #else int size = file_size_ex(filename); #endif int pro = (size == 768)? false: true; /* is Animator Pro format? */ div_t d = div(size-8, 3); Palette *pal = NULL; int c, r, g, b; FILE *f; if (!(size) || (pro && d.rem)) /* invalid format */ return NULL; f = fopen(filename, "rb"); if (!f) return NULL; /* Animator format */ if (!pro) { pal = new Palette(FrameNumber(0), 256); for (c=0; c<256; c++) { r = fgetc(f); g = fgetc(f); b = fgetc(f); if (ferror(f)) break; pal->setEntry(c, _rgba(_rgb_scale_6[MID(0, r, 63)], _rgb_scale_6[MID(0, g, 63)], _rgb_scale_6[MID(0, b, 63)], 255)); } } /* Animator Pro format */ else { int magic, version; fgetl(f); /* skip file size */ magic = fgetw(f); /* file format identifier */ version = fgetw(f); /* version file */ /* unknown format */ if (magic != PROCOL_MAGIC_NUMBER || version != 0) { fclose(f); return NULL; } pal = new Palette(FrameNumber(0), MIN(d.quot, 256)); for (c=0; c<pal->size(); c++) { r = fgetc(f); g = fgetc(f); b = fgetc(f); if (ferror(f)) break; pal->setEntry(c, _rgba(MID(0, r, 255), MID(0, g, 255), MID(0, b, 255), 255)); } } fclose(f); return pal; }
void onImport() { // The user don't select a sheet yet. if (!m_document) { Alert::show("Import Sprite Sheet<<Select a sprite first.||&Close"); return; } // The list of frames imported from the sheet std::vector<Image*> animation; try { Sprite* sprite = m_document->getSprite(); FrameNumber currentFrame = m_context->getActiveLocation().frame(); // As first step, we cut each tile and add them into "animation" list. for (int y=m_rect.y; y<sprite->getHeight(); y += m_rect.h) { for (int x=m_rect.x; x<sprite->getWidth(); x += m_rect.w) { base::UniquePtr<Image> resultImage(Image::create(sprite->getPixelFormat(), m_rect.w, m_rect.h)); // Clear the image with mask color. image_clear(resultImage, 0); // Render the portion of sheet. sprite->render(resultImage, -x, -y, currentFrame); animation.push_back(resultImage); resultImage.release(); } } if (animation.size() == 0) { Alert::show("Import Sprite Sheet" "<<The specified rectangle does not create any tile." "<<Select a rectangle inside the sprite region." "||&OK"); return; } // The following steps modify the sprite, so we wrap all // operations in a undo-transaction. ContextWriter writer(m_context); UndoTransaction undoTransaction(writer.context(), "Import Sprite Sheet", undo::ModifyDocument); DocumentApi api = m_document->getApi(); // Add the layer in the sprite. LayerImage* resultLayer = api.newLayer(sprite); // Add all frames+cels to the new layer for (size_t i=0; i<animation.size(); ++i) { int indexInStock; // Add the image into the sprite's stock indexInStock = api.addImageInStock(sprite, animation[i]); animation[i] = NULL; // Create the cel. base::UniquePtr<Cel> resultCel(new Cel(FrameNumber(i), indexInStock)); // Add the cel in the layer. api.addCel(resultLayer, resultCel); resultCel.release(); } // Copy the list of layers (because we will modify it in the iteration). LayerList layers = sprite->getFolder()->getLayersList(); // Remove all other layers for (LayerIterator it=layers.begin(), end=layers.end(); it!=end; ++it) { if (*it != resultLayer) api.removeLayer(*it); } // Change the number of frames api.setTotalFrames(sprite, FrameNumber(animation.size())); // Set the size of the sprite to the tile size. api.setSpriteSize(sprite, m_rect.w, m_rect.h); undoTransaction.commit(); } catch (...) { for (size_t i=0; i<animation.size(); ++i) delete animation[i]; throw; } update_screen_for_document(m_document); closeWindow(NULL); }
Document* Document::duplicate(DuplicateType type) const { const Sprite* sourceSprite = getSprite(); UniquePtr<Sprite> spriteCopyPtr(new Sprite(sourceSprite->getPixelFormat(), sourceSprite->getWidth(), sourceSprite->getHeight(), sourceSprite->getPalette(FrameNumber(0))->size())); UniquePtr<Document> documentCopy(new Document(spriteCopyPtr)); Sprite* spriteCopy = spriteCopyPtr.release(); spriteCopy->setTotalFrames(sourceSprite->getTotalFrames()); // Copy frames duration for (FrameNumber i(0); i < sourceSprite->getTotalFrames(); ++i) spriteCopy->setFrameDuration(i, sourceSprite->getFrameDuration(i)); // Copy color palettes { PalettesList::const_iterator it = sourceSprite->getPalettes().begin(); PalettesList::const_iterator end = sourceSprite->getPalettes().end(); for (; it != end; ++it) { const Palette* pal = *it; spriteCopy->setPalette(pal, true); } } switch (type) { case DuplicateExactCopy: // Disable the undo documentCopy->getUndo()->setEnabled(false); // Copy the layer folder copyLayerContent(getSprite()->getFolder(), documentCopy, spriteCopy->getFolder()); // Re-enable the undo documentCopy->getUndo()->setEnabled(true); break; case DuplicateWithFlattenLayers: { // Flatten layers ASSERT(sourceSprite->getFolder() != NULL); LayerImage* flatLayer = create_flatten_layer_copy (spriteCopy, sourceSprite->getFolder(), gfx::Rect(0, 0, sourceSprite->getWidth(), sourceSprite->getHeight()), FrameNumber(0), sourceSprite->getLastFrame()); // Add and select the new flat layer spriteCopy->getFolder()->addLayer(flatLayer); // Configure the layer as background only if the original // sprite has a background layer. if (sourceSprite->getBackgroundLayer() != NULL) flatLayer->configureAsBackground(); } break; } documentCopy->setMask(getMask()); documentCopy->m_maskVisible = m_maskVisible; documentCopy->generateMaskBoundaries(); return documentCopy.release(); }
void copy_cel(ContextWriter& writer) { Document* document = writer.document(); Sprite* sprite = writer.sprite(); UndoTransaction undo(writer.context(), "Move Cel", undo::ModifyDocument); Cel *src_cel, *dst_cel; ASSERT(src_layer != NULL); ASSERT(dst_layer != NULL); ASSERT(src_frame >= 0 && src_frame < sprite->getTotalFrames()); ASSERT(dst_frame >= 0 && dst_frame < sprite->getTotalFrames()); src_cel = static_cast<LayerImage*>(src_layer)->getCel(src_frame); dst_cel = static_cast<LayerImage*>(dst_layer)->getCel(dst_frame); // Remove the 'dst_cel' (if it exists) because it must be replaced // with 'src_cel' if ((dst_cel != NULL) && (!dst_layer->isBackground() || src_cel != NULL)) remove_cel(sprite, undo, static_cast<LayerImage*>(dst_layer), dst_cel); // Move the cel in the same layer. if (src_cel != NULL) { Image *src_image = sprite->getStock()->getImage(src_cel->getImage()); Image *dst_image; int image_index; int dst_cel_x; int dst_cel_y; int dst_cel_opacity; // If we are moving a cel from a transparent layer to the // background layer, we have to clear the background of the image. if (!src_layer->isBackground() && dst_layer->isBackground()) { dst_image = image_crop(src_image, -src_cel->getX(), -src_cel->getY(), sprite->getWidth(), sprite->getHeight(), 0); image_clear(dst_image, app_get_color_to_clear_layer(dst_layer)); image_merge(dst_image, src_image, src_cel->getX(), src_cel->getY(), 255, BLEND_MODE_NORMAL); dst_cel_x = 0; dst_cel_y = 0; dst_cel_opacity = 255; } else { dst_image = Image::createCopy(src_image); dst_cel_x = src_cel->getX(); dst_cel_y = src_cel->getY(); dst_cel_opacity = src_cel->getOpacity(); } // Add the image in the stock image_index = sprite->getStock()->addImage(dst_image); if (undo.isEnabled()) undo.pushUndoer(new undoers::AddImage(undo.getObjects(), sprite->getStock(), image_index)); // Create the new cel dst_cel = new Cel(dst_frame, image_index); dst_cel->setPosition(dst_cel_x, dst_cel_y); dst_cel->setOpacity(dst_cel_opacity); if (undo.isEnabled()) undo.pushUndoer(new undoers::AddCel(undo.getObjects(), dst_layer, dst_cel)); static_cast<LayerImage*>(dst_layer)->addCel(dst_cel); } undo.commit(); document->notifyCelCopied(src_layer, src_frame, dst_layer, dst_frame); set_frame_to_handle(NULL, FrameNumber(0), NULL, FrameNumber(0)); }
void move_cel(ContextWriter& writer) { Document* document = writer.document(); Sprite* sprite = writer.sprite(); Cel *src_cel, *dst_cel; ASSERT(src_layer != NULL); ASSERT(dst_layer != NULL); ASSERT(src_frame >= 0 && src_frame < sprite->getTotalFrames()); ASSERT(dst_frame >= 0 && dst_frame < sprite->getTotalFrames()); if (src_layer->isBackground()) { copy_cel(writer); return; } src_cel = static_cast<LayerImage*>(src_layer)->getCel(src_frame); dst_cel = static_cast<LayerImage*>(dst_layer)->getCel(dst_frame); UndoTransaction undo(writer.context(), "Move Cel", undo::ModifyDocument); /* remove the 'dst_cel' (if it exists) because it must be replaced with 'src_cel' */ if ((dst_cel != NULL) && (!dst_layer->isBackground() || src_cel != NULL)) remove_cel(sprite, undo, static_cast<LayerImage*>(dst_layer), dst_cel); /* move the cel in the same layer */ if (src_cel != NULL) { if (src_layer == dst_layer) { if (undo.isEnabled()) undo.pushUndoer(new undoers::SetCelFrame(undo.getObjects(), src_cel)); src_cel->setFrame(dst_frame); } /* move the cel in different layers */ else { if (undo.isEnabled()) undo.pushUndoer(new undoers::RemoveCel(undo.getObjects(), src_layer, src_cel)); static_cast<LayerImage*>(src_layer)->removeCel(src_cel); src_cel->setFrame(dst_frame); /* if we are moving a cel from a transparent layer to the background layer, we have to clear the background of the image */ if (!src_layer->isBackground() && dst_layer->isBackground()) { Image *src_image = sprite->getStock()->getImage(src_cel->getImage()); Image *dst_image = image_crop(src_image, -src_cel->getX(), -src_cel->getY(), sprite->getWidth(), sprite->getHeight(), 0); if (undo.isEnabled()) { undo.pushUndoer(new undoers::ReplaceImage(undo.getObjects(), sprite->getStock(), src_cel->getImage())); undo.pushUndoer(new undoers::SetCelPosition(undo.getObjects(), src_cel)); undo.pushUndoer(new undoers::SetCelOpacity(undo.getObjects(), src_cel)); } image_clear(dst_image, app_get_color_to_clear_layer(dst_layer)); image_merge(dst_image, src_image, src_cel->getX(), src_cel->getY(), 255, BLEND_MODE_NORMAL); src_cel->setPosition(0, 0); src_cel->setOpacity(255); sprite->getStock()->replaceImage(src_cel->getImage(), dst_image); image_free(src_image); } if (undo.isEnabled()) undo.pushUndoer(new undoers::AddCel(undo.getObjects(), dst_layer, src_cel)); static_cast<LayerImage*>(dst_layer)->addCel(src_cel); } } undo.commit(); document->notifyCelMoved(src_layer, src_frame, dst_layer, dst_frame); set_frame_to_handle(NULL, FrameNumber(0), NULL, FrameNumber(0)); }
void DocumentApi::setPixelFormat(Sprite* sprite, PixelFormat newFormat, DitheringMethod dithering_method) { Image* old_image; Image* new_image; int c; if (sprite->getPixelFormat() == newFormat) return; // Change pixel format of the stock of images. DocumentUndo* undo = m_document->getUndo(); if (undo->isEnabled()) m_undoers->pushUndoer(new undoers::SetStockPixelFormat(getObjects(), sprite->getStock())); sprite->getStock()->setPixelFormat(newFormat); // TODO Review this, why we use the palette in frame 0? FrameNumber frame(0); // Use the rgbmap for the specified sprite const RgbMap* rgbmap = sprite->getRgbMap(frame); for (c=0; c<sprite->getStock()->size(); c++) { old_image = sprite->getStock()->getImage(c); if (!old_image) continue; new_image = quantization::convert_pixel_format (old_image, newFormat, dithering_method, rgbmap, sprite->getPalette(frame), sprite->getBackgroundLayer() != NULL); replaceStockImage(sprite, c, new_image); } // Change sprite's pixel format. if (undo->isEnabled()) m_undoers->pushUndoer(new undoers::SetSpritePixelFormat(getObjects(), sprite)); sprite->setPixelFormat(newFormat); // Regenerate extras m_document->destroyExtraCel(); // When we are converting to grayscale color mode, we've to destroy // all palettes and put only one grayscaled-palette at the first // frame. if (newFormat == IMAGE_GRAYSCALE) { // Add undoers to revert all palette changes. if (undo->isEnabled()) { PalettesList palettes = sprite->getPalettes(); for (PalettesList::iterator it = palettes.begin(); it != palettes.end(); ++it) { Palette* palette = *it; m_undoers->pushUndoer(new undoers::RemovePalette( getObjects(), sprite, palette->getFrame())); } m_undoers->pushUndoer(new undoers::AddPalette( getObjects(), sprite, FrameNumber(0))); } // It's a UniquePtr because setPalette'll create a copy of "graypal". UniquePtr<Palette> graypal(Palette::createGrayscale()); sprite->resetPalettes(); sprite->setPalette(graypal, true); } }