|
@@ -188,7 +188,7 @@ void our_CanvasDrawTextures(){
|
|
for(int row=0;row<OUR_TEX_TILES_PER_ROW;row++){
|
|
for(int row=0;row<OUR_TEX_TILES_PER_ROW;row++){
|
|
if(!l->TexTiles[row]) continue;
|
|
if(!l->TexTiles[row]) continue;
|
|
for(int col=0;col<OUR_TEX_TILES_PER_ROW;col++){
|
|
for(int col=0;col<OUR_TEX_TILES_PER_ROW;col++){
|
|
- if(!l->TexTiles[row][col]) continue;
|
|
|
|
|
|
+ if(!l->TexTiles[row][col] || !l->TexTiles[row][col]->Texture) continue;
|
|
int sx=((real)col-OUR_TEX_TILE_CTR-0.5)*OUR_TEX_TILE_W_USE-OUR_TEX_TILE_SEAM,sy=((real)row-OUR_TEX_TILE_CTR-0.5)*OUR_TEX_TILE_W_USE-OUR_TEX_TILE_SEAM;
|
|
int sx=((real)col-OUR_TEX_TILE_CTR-0.5)*OUR_TEX_TILE_W_USE-OUR_TEX_TILE_SEAM,sy=((real)row-OUR_TEX_TILE_CTR-0.5)*OUR_TEX_TILE_W_USE-OUR_TEX_TILE_SEAM;
|
|
real pad=(real)OUR_TEX_TILE_SEAM/OUR_TEX_TILE_W; int seam=OUR_TEX_TILE_SEAM;
|
|
real pad=(real)OUR_TEX_TILE_SEAM/OUR_TEX_TILE_W; int seam=OUR_TEX_TILE_SEAM;
|
|
tnsDraw2DTextureArg(l->TexTiles[row][col]->Texture,sx+seam,sy+OUR_TEX_TILE_W-seam,OUR_TEX_TILE_W-seam*2,-OUR_TEX_TILE_W+seam*2,0,pad,pad,pad,pad);
|
|
tnsDraw2DTextureArg(l->TexTiles[row][col]->Texture,sx+seam,sy+OUR_TEX_TILE_W-seam,OUR_TEX_TILE_W-seam*2,-OUR_TEX_TILE_W+seam*2,0,pad,pad,pad,pad);
|
|
@@ -205,7 +205,7 @@ void our_CanvasDrawTiles(){
|
|
for(int row=0;row<OUR_TEX_TILES_PER_ROW;row++){
|
|
for(int row=0;row<OUR_TEX_TILES_PER_ROW;row++){
|
|
if(!l->TexTiles[row]) continue;
|
|
if(!l->TexTiles[row]) continue;
|
|
for(int col=0;col<OUR_TEX_TILES_PER_ROW;col++){
|
|
for(int col=0;col<OUR_TEX_TILES_PER_ROW;col++){
|
|
- if(!l->TexTiles[row][col]) continue;
|
|
|
|
|
|
+ if(!l->TexTiles[row][col] || !l->TexTiles[row][col]->Texture) continue;
|
|
int sx=((real)col-OUR_TEX_TILE_CTR-0.5)*OUR_TEX_TILE_W_USE-OUR_TEX_TILE_SEAM,sy=((real)row-OUR_TEX_TILE_CTR-0.5)*OUR_TEX_TILE_W_USE-OUR_TEX_TILE_SEAM;
|
|
int sx=((real)col-OUR_TEX_TILE_CTR-0.5)*OUR_TEX_TILE_W_USE-OUR_TEX_TILE_SEAM,sy=((real)row-OUR_TEX_TILE_CTR-0.5)*OUR_TEX_TILE_W_USE-OUR_TEX_TILE_SEAM;
|
|
//tnsVertex2d(sx, sy); tnsVertex2d(sx+OUR_TEX_TILE_W,sy);
|
|
//tnsVertex2d(sx, sy); tnsVertex2d(sx+OUR_TEX_TILE_W,sy);
|
|
//tnsVertex2d(sx+OUR_TEX_TILE_W, sy+OUR_TEX_TILE_W); tnsVertex2d(sx,sy+OUR_TEX_TILE_W);
|
|
//tnsVertex2d(sx+OUR_TEX_TILE_W, sy+OUR_TEX_TILE_W); tnsVertex2d(sx,sy+OUR_TEX_TILE_W);
|
|
@@ -304,15 +304,31 @@ void our_CanvasDrawOverlay(laUiItem* ui,int h){
|
|
}
|
|
}
|
|
|
|
|
|
OurLayer* our_NewLayer(char* name){
|
|
OurLayer* our_NewLayer(char* name){
|
|
- OurLayer* l=memAcquire(sizeof(OurLayer)); strSafeSet(&l->Name,name); lstPushItem(&Our->Layers, l);
|
|
|
|
|
|
+ OurLayer* l=memAcquireHyper(sizeof(OurLayer)); strSafeSet(&l->Name,name); lstPushItem(&Our->Layers, l);
|
|
memAssignRef(Our, &Our->CurrentLayer, l);
|
|
memAssignRef(Our, &Our->CurrentLayer, l);
|
|
return l;
|
|
return l;
|
|
}
|
|
}
|
|
void our_RemoveLayer(OurLayer* l){
|
|
void our_RemoveLayer(OurLayer* l){
|
|
strSafeDestroy(&l->Name); lstRemoveItem(&Our->Layers, l);
|
|
strSafeDestroy(&l->Name); lstRemoveItem(&Our->Layers, l);
|
|
if(Our->CurrentLayer==l){ OurLayer* nl=l->Item.pPrev?l->Item.pPrev:l->Item.pNext; memAssignRef(Our, &Our->CurrentLayer, nl); }
|
|
if(Our->CurrentLayer==l){ OurLayer* nl=l->Item.pPrev?l->Item.pPrev:l->Item.pNext; memAssignRef(Our, &Our->CurrentLayer, nl); }
|
|
|
|
+ for(int row=0;row<OUR_TEX_TILES_PER_ROW;row++){ if(!l->TexTiles[row]) continue;
|
|
|
|
+ for(int col=0;col<OUR_TEX_TILES_PER_ROW;col++){ if(!l->TexTiles[row][col]) continue;
|
|
|
|
+ if(l->TexTiles[row][col]->Texture) tnsDeleteTexture(l->TexTiles[row][col]->Texture); l->TexTiles[row][col]->Texture=0;
|
|
|
|
+ if(l->TexTiles[row][col]->Data) free(l->TexTiles[row][col]->Data); l->TexTiles[row][col]->Data=0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
memLeave(l);
|
|
memLeave(l);
|
|
}
|
|
}
|
|
|
|
+void ourbeforefree_Layer(OurLayer* l){
|
|
|
|
+ for(int row=0;row<OUR_TEX_TILES_PER_ROW;row++){ if(!l->TexTiles[row]) continue;
|
|
|
|
+ for(int col=0;col<OUR_TEX_TILES_PER_ROW;col++){ if(!l->TexTiles[row][col]) continue;
|
|
|
|
+ if(l->TexTiles[row][col]->Texture) tnsDeleteTexture(l->TexTiles[row][col]->Texture); l->TexTiles[row][col]->Texture=0;
|
|
|
|
+ if(l->TexTiles[row][col]->Data) free(l->TexTiles[row][col]->Data); l->TexTiles[row][col]->Data=0;
|
|
|
|
+ memFree(l->TexTiles[row][col]);
|
|
|
|
+ }
|
|
|
|
+ memFree(l->TexTiles[row]); l->TexTiles[row]=0;
|
|
|
|
+ }
|
|
|
|
+}
|
|
OurBrush* our_NewBrush(char* name, real Size, real Hardness, real DabsPerSize, real Transparency, real Smudge, real SmudgeResampleLength,
|
|
OurBrush* our_NewBrush(char* name, real Size, real Hardness, real DabsPerSize, real Transparency, real Smudge, real SmudgeResampleLength,
|
|
int PressureSize, int PressureHardness, int PressureTransparency, int PressureSmudge){
|
|
int PressureSize, int PressureHardness, int PressureTransparency, int PressureSmudge){
|
|
OurBrush* b=memAcquireHyper(sizeof(OurBrush)); strSafeSet(&b->Name,name); lstAppendItem(&Our->Brushes, b);
|
|
OurBrush* b=memAcquireHyper(sizeof(OurBrush)); strSafeSet(&b->Name,name); lstAppendItem(&Our->Brushes, b);
|
|
@@ -328,6 +344,12 @@ void our_RemoveBrush(OurBrush* b){
|
|
memLeave(b);
|
|
memLeave(b);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+int our_BufferAnythingVisible(uint16_t* buf, int elemcount){
|
|
|
|
+ for(int i=0;i<elemcount;i++){
|
|
|
|
+ uint16_t* rgba=&buf[i*4]; if(rgba[3]) return 1;
|
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
void our_LayerEnsureTiles(OurLayer* ol, real xmin,real xmax, real ymin,real ymax, int Aligned, int *tl, int *tr, int* tu, int* tb){
|
|
void our_LayerEnsureTiles(OurLayer* ol, real xmin,real xmax, real ymin,real ymax, int Aligned, int *tl, int *tr, int* tu, int* tb){
|
|
int l,r,u,b;
|
|
int l,r,u,b;
|
|
if(Aligned){
|
|
if(Aligned){
|
|
@@ -351,6 +373,7 @@ void our_LayerEnsureTiles(OurLayer* ol, real xmin,real xmax, real ymin,real ymax
|
|
if(ol->TexTiles[row][col]) continue;
|
|
if(ol->TexTiles[row][col]) continue;
|
|
ol->TexTiles[row][col]=memAcquireSimple(sizeof(OurTexTile));
|
|
ol->TexTiles[row][col]=memAcquireSimple(sizeof(OurTexTile));
|
|
ol->TexTiles[row][col]->Texture=tnsCreate2DTexture(GL_RGBA16,OUR_TEX_TILE_W,OUR_TEX_TILE_W,0);
|
|
ol->TexTiles[row][col]->Texture=tnsCreate2DTexture(GL_RGBA16,OUR_TEX_TILE_W,OUR_TEX_TILE_W,0);
|
|
|
|
+ ol->TexTiles[row][col]->row=row; ol->TexTiles[row][col]->col=col;
|
|
uint16_t initColor[]={0,0,0,0};
|
|
uint16_t initColor[]={0,0,0,0};
|
|
glClearTexImage(ol->TexTiles[row][col]->Texture->GLTexHandle, 0, GL_RGBA, GL_UNSIGNED_SHORT, 0);
|
|
glClearTexImage(ol->TexTiles[row][col]->Texture->GLTexHandle, 0, GL_RGBA, GL_UNSIGNED_SHORT, 0);
|
|
}
|
|
}
|
|
@@ -367,7 +390,7 @@ void our_TileTextureToImage(OurTexTile* ot, int SX, int SY){
|
|
for(int row=0;row<OUR_TEX_TILE_W_USE;row++){
|
|
for(int row=0;row<OUR_TEX_TILE_W_USE;row++){
|
|
memcpy(&Our->ImageBuffer[((SY+row)*Our->ImageW+SX)*4],&ot->Data[(row*OUR_TEX_TILE_W_USE)*4],sizeof(uint16_t)*4*OUR_TEX_TILE_W_USE);
|
|
memcpy(&Our->ImageBuffer[((SY+row)*Our->ImageW+SX)*4],&ot->Data[(row*OUR_TEX_TILE_W_USE)*4],sizeof(uint16_t)*4*OUR_TEX_TILE_W_USE);
|
|
}
|
|
}
|
|
- free(ot->Data);
|
|
|
|
|
|
+ free(ot->Data); ot->Data=0;
|
|
}
|
|
}
|
|
void our_TileImageToTexture(OurTexTile* ot, int SX, int SY){
|
|
void our_TileImageToTexture(OurTexTile* ot, int SX, int SY){
|
|
int pl=(SX!=0)?OUR_TEX_TILE_SEAM:0, pr=((SX+OUR_TEX_TILE_W_USE)!=Our->ImageW)?OUR_TEX_TILE_SEAM:0;
|
|
int pl=(SX!=0)?OUR_TEX_TILE_SEAM:0, pr=((SX+OUR_TEX_TILE_W_USE)!=Our->ImageW)?OUR_TEX_TILE_SEAM:0;
|
|
@@ -377,11 +400,14 @@ void our_TileImageToTexture(OurTexTile* ot, int SX, int SY){
|
|
for(int row=0;row<height;row++){
|
|
for(int row=0;row<height;row++){
|
|
memcpy(&ot->Data[((row)*width)*4],&Our->ImageBuffer[((SY+row-pu)*Our->ImageW+SX-pl)*4],sizeof(uint16_t)*4*width);
|
|
memcpy(&ot->Data[((row)*width)*4],&Our->ImageBuffer[((SY+row-pu)*Our->ImageW+SX-pl)*4],sizeof(uint16_t)*4*width);
|
|
}
|
|
}
|
|
- tnsBindTexture(ot->Texture);
|
|
|
|
- glTexSubImage2D(GL_TEXTURE_2D, 0, OUR_TEX_TILE_SEAM-pl, OUR_TEX_TILE_SEAM-pu, width, height, GL_RGBA, GL_UNSIGNED_SHORT, ot->Data);
|
|
|
|
- free(ot->Data);
|
|
|
|
|
|
+ if(!our_BufferAnythingVisible(ot->Data, bufsize/sizeof(uint16_t)/4)){ tnsDeleteTexture(ot->Texture); ot->Texture=0; }
|
|
|
|
+ else{
|
|
|
|
+ tnsBindTexture(ot->Texture);
|
|
|
|
+ glTexSubImage2D(GL_TEXTURE_2D, 0, OUR_TEX_TILE_SEAM-pl, OUR_TEX_TILE_SEAM-pu, width, height, GL_RGBA, GL_UNSIGNED_SHORT, ot->Data);
|
|
|
|
+ }
|
|
|
|
+ free(ot->Data); ot->Data=0;
|
|
}
|
|
}
|
|
-int our_LayerEnsureImageBuffer(OurLayer* ol){
|
|
|
|
|
|
+int our_LayerEnsureImageBuffer(OurLayer* ol, int OnlyCalculate){
|
|
int l=1000,r=-1000,u=-1000,b=1000; int any=0;
|
|
int l=1000,r=-1000,u=-1000,b=1000; int any=0;
|
|
for(int row=0;row<OUR_TEX_TILES_PER_ROW;row++){ if(!ol->TexTiles[row]) continue;
|
|
for(int row=0;row<OUR_TEX_TILES_PER_ROW;row++){ if(!ol->TexTiles[row]) continue;
|
|
if(row<b) b=row; if(row>u) u=row;
|
|
if(row<b) b=row; if(row>u) u=row;
|
|
@@ -392,8 +418,10 @@ int our_LayerEnsureImageBuffer(OurLayer* ol){
|
|
if(!any) return 0;
|
|
if(!any) return 0;
|
|
Our->ImageW = OUR_TEX_TILE_W_USE*(r-l+1); Our->ImageH = OUR_TEX_TILE_W_USE*(u-b+1);
|
|
Our->ImageW = OUR_TEX_TILE_W_USE*(r-l+1); Our->ImageH = OUR_TEX_TILE_W_USE*(u-b+1);
|
|
Our->ImageX =((real)l-OUR_TEX_TILE_CTR-0.5)*OUR_TEX_TILE_W_USE; Our->ImageY=((real)b-OUR_TEX_TILE_CTR-0.5)*OUR_TEX_TILE_W_USE;
|
|
Our->ImageX =((real)l-OUR_TEX_TILE_CTR-0.5)*OUR_TEX_TILE_W_USE; Our->ImageY=((real)b-OUR_TEX_TILE_CTR-0.5)*OUR_TEX_TILE_W_USE;
|
|
- if(Our->ImageBuffer) free(Our->ImageBuffer);
|
|
|
|
- Our->ImageBuffer = calloc(Our->ImageW*4,Our->ImageH*sizeof(uint16_t));
|
|
|
|
|
|
+ if(!OnlyCalculate){
|
|
|
|
+ if(Our->ImageBuffer) free(Our->ImageBuffer);
|
|
|
|
+ Our->ImageBuffer = calloc(Our->ImageW*4,Our->ImageH*sizeof(uint16_t));
|
|
|
|
+ }
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
void our_LayerToImageBuffer(OurLayer* ol){
|
|
void our_LayerToImageBuffer(OurLayer* ol){
|
|
@@ -412,16 +440,30 @@ void our_LayerToTexture(OurLayer* ol){
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-int our_LayerExportPNG(OurLayer* l, FILE* fp){
|
|
|
|
- if(!l||!fp) return 0;
|
|
|
|
|
|
+static void _our_png_write(png_structp png_ptr, png_bytep data, png_size_t length){
|
|
|
|
+ OurLayerWrite* LayerWrite=png_get_io_ptr(png_ptr);
|
|
|
|
+ arrEnsureLength(&LayerWrite->data,LayerWrite->NextData+length,&LayerWrite->MaxData,sizeof(unsigned char));
|
|
|
|
+ memcpy(&LayerWrite->data[LayerWrite->NextData], data, length);
|
|
|
|
+ LayerWrite->NextData+=length;
|
|
|
|
+}
|
|
|
|
+int our_LayerExportPNG(OurLayer* l, FILE* fp, int WriteToBuffer, void** buf, int* sizeof_buf){
|
|
|
|
+ if(!l||(!fp&&!WriteToBuffer)) return 0;
|
|
|
|
|
|
- if(!our_LayerEnsureImageBuffer(l)) return 0;
|
|
|
|
|
|
+ if(!our_LayerEnsureImageBuffer(l, 0)) return 0;
|
|
|
|
|
|
our_LayerToImageBuffer(l);
|
|
our_LayerToImageBuffer(l);
|
|
|
|
|
|
png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);
|
|
png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);
|
|
png_infop info_ptr = png_create_info_struct(png_ptr);
|
|
png_infop info_ptr = png_create_info_struct(png_ptr);
|
|
- png_init_io(png_ptr, fp);
|
|
|
|
|
|
+
|
|
|
|
+ OurLayerWrite LayerWrite={0};
|
|
|
|
+
|
|
|
|
+ if(WriteToBuffer){
|
|
|
|
+ arrEnsureLength(&LayerWrite.data,0,&LayerWrite.MaxData,sizeof(unsigned char));
|
|
|
|
+ png_set_write_fn(png_ptr,&LayerWrite,_our_png_write,0);
|
|
|
|
+ }else{
|
|
|
|
+ png_init_io(png_ptr, fp);
|
|
|
|
+ }
|
|
|
|
|
|
png_set_IHDR(png_ptr, info_ptr,Our->ImageW,Our->ImageH,16,PNG_COLOR_TYPE_RGBA,PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_BASE,PNG_FILTER_TYPE_BASE);
|
|
png_set_IHDR(png_ptr, info_ptr,Our->ImageW,Our->ImageH,16,PNG_COLOR_TYPE_RGBA,PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_BASE,PNG_FILTER_TYPE_BASE);
|
|
// Should not set gamma, we should set either srgb chunk or iccp. Gimp bug: https://gitlab.gnome.org/GNOME/gimp/-/issues/5363
|
|
// Should not set gamma, we should set either srgb chunk or iccp. Gimp bug: https://gitlab.gnome.org/GNOME/gimp/-/issues/5363
|
|
@@ -444,21 +486,30 @@ int our_LayerExportPNG(OurLayer* l, FILE* fp){
|
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
|
free(Our->ImageBuffer); Our->ImageBuffer=0;
|
|
free(Our->ImageBuffer); Our->ImageBuffer=0;
|
|
|
|
|
|
|
|
+ if(WriteToBuffer){ *buf=LayerWrite.data; *sizeof_buf=LayerWrite.NextData; }
|
|
|
|
+
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
-void our_EnsureImageBufferOnRead(OurLayer*l, int W, int H, int Align, int StartX, int StartY){
|
|
|
|
|
|
+void our_EnsureImageBufferOnRead(OurLayer*l, int W, int H, int UseOffsets, int StartX, int StartY){
|
|
int tw=W/OUR_TEX_TILE_W_USE, th=H/OUR_TEX_TILE_W_USE;
|
|
int tw=W/OUR_TEX_TILE_W_USE, th=H/OUR_TEX_TILE_W_USE;
|
|
int w=tw*OUR_TEX_TILE_W_USE, h=th*OUR_TEX_TILE_W_USE;
|
|
int w=tw*OUR_TEX_TILE_W_USE, h=th*OUR_TEX_TILE_W_USE;
|
|
if(w<W){ tw+=1; w+=OUR_TEX_TILE_W_USE; } if(h<H){ th+=1; h+=OUR_TEX_TILE_W_USE; }
|
|
if(w<W){ tw+=1; w+=OUR_TEX_TILE_W_USE; } if(h<H){ th+=1; h+=OUR_TEX_TILE_W_USE; }
|
|
|
|
|
|
- int ix=-tw/2*OUR_TEX_TILE_W_USE-OUR_TEX_TILE_W_USE/2, iy=th/2*OUR_TEX_TILE_W_USE+OUR_TEX_TILE_W_USE/2; int tl,tr,tu,tb;
|
|
|
|
|
|
+ int ix=UseOffsets?StartX:(-tw/2*OUR_TEX_TILE_W_USE-OUR_TEX_TILE_W_USE/2);
|
|
|
|
+ int iy=UseOffsets?StartY:(th/2*OUR_TEX_TILE_W_USE+OUR_TEX_TILE_W_USE/2);
|
|
|
|
+ int tl,tr,tu,tb;
|
|
our_LayerEnsureTiles(l,ix,ix+W,iy-H,iy,1,&tl,&tr,&tu,&tb);
|
|
our_LayerEnsureTiles(l,ix,ix+W,iy-H,iy,1,&tl,&tr,&tu,&tb);
|
|
- our_LayerEnsureImageBuffer(l);
|
|
|
|
|
|
+ our_LayerEnsureImageBuffer(l, 0);
|
|
Our->LoadX = ix-Our->ImageX; Our->LoadY = Our->ImageY+Our->ImageH-iy;
|
|
Our->LoadX = ix-Our->ImageX; Our->LoadY = Our->ImageY+Our->ImageH-iy;
|
|
}
|
|
}
|
|
-int our_LayerImportPNG(OurLayer* l, FILE* fp, int UseProfile){
|
|
|
|
|
|
+static void _our_png_read(png_struct *ps, png_byte *data, png_size_t length){
|
|
|
|
+ OurLayerRead *LayerRead = (OurLayerRead*)png_get_io_ptr(ps);
|
|
|
|
+ memcpy(data,&LayerRead->data[LayerRead->NextData],length);
|
|
|
|
+ LayerRead->NextData+=length;
|
|
|
|
+}
|
|
|
|
+int our_LayerImportPNG(OurLayer* l, FILE* fp, void* buf, int UseProfile, int UseOffsets, int StartX, int StartY){
|
|
int result=0;
|
|
int result=0;
|
|
- if(!fp || !l) return 0;
|
|
|
|
|
|
+ if((!fp&&!buf) || !l) return 0;
|
|
|
|
|
|
int srgb_intent = 0;
|
|
int srgb_intent = 0;
|
|
png_charp icc_profile_name = NULL;
|
|
png_charp icc_profile_name = NULL;
|
|
@@ -474,10 +525,16 @@ int our_LayerImportPNG(OurLayer* l, FILE* fp, int UseProfile){
|
|
png_bytep icc_profile = NULL;
|
|
png_bytep icc_profile = NULL;
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+ OurLayerRead LayerRead={0};
|
|
|
|
+
|
|
png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) { return 0; }
|
|
png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) { return 0; }
|
|
png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { return 0; }
|
|
png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { return 0; }
|
|
if (setjmp(png_jmpbuf(png_ptr))) { goto cleanup_png_read; }
|
|
if (setjmp(png_jmpbuf(png_ptr))) { goto cleanup_png_read; }
|
|
- png_init_io(png_ptr, fp);
|
|
|
|
|
|
+ if(buf){
|
|
|
|
+ LayerRead.data=buf; png_set_read_fn(png_ptr, &LayerRead, _our_png_read);
|
|
|
|
+ }else{
|
|
|
|
+ png_init_io(png_ptr, fp);
|
|
|
|
+ }
|
|
png_read_info(png_ptr, info_ptr);
|
|
png_read_info(png_ptr, info_ptr);
|
|
png_set_swap(png_ptr);
|
|
png_set_swap(png_ptr);
|
|
|
|
|
|
@@ -548,7 +605,7 @@ int our_LayerImportPNG(OurLayer* l, FILE* fp, int UseProfile){
|
|
int W = png_get_image_width(png_ptr, info_ptr);
|
|
int W = png_get_image_width(png_ptr, info_ptr);
|
|
int H = png_get_image_height(png_ptr, info_ptr);
|
|
int H = png_get_image_height(png_ptr, info_ptr);
|
|
|
|
|
|
- our_EnsureImageBufferOnRead(l,W,H,1,0,0);
|
|
|
|
|
|
+ our_EnsureImageBufferOnRead(l,W,H,UseOffsets,StartX,StartY);
|
|
|
|
|
|
for(int i=0;i<H;i++){
|
|
for(int i=0;i<H;i++){
|
|
png_read_row(png_ptr, &Our->ImageBuffer[((H-i-1+Our->LoadY)*Our->ImageW+Our->LoadX)*4], NULL);
|
|
png_read_row(png_ptr, &Our->ImageBuffer[((H-i-1+Our->LoadY)*Our->ImageW+Our->LoadX)*4], NULL);
|
|
@@ -740,7 +797,7 @@ int ourmod_ExportLayer(laOperator* a, laEvent* e){
|
|
if (a->ConfirmData->StrData){
|
|
if (a->ConfirmData->StrData){
|
|
FILE* fp=fopen(a->ConfirmData->StrData,"wb");
|
|
FILE* fp=fopen(a->ConfirmData->StrData,"wb");
|
|
if(!fp) return LA_FINISHED;
|
|
if(!fp) return LA_FINISHED;
|
|
- our_LayerExportPNG(Our->CurrentLayer, fp);
|
|
|
|
|
|
+ our_LayerExportPNG(Our->CurrentLayer, fp, 0, 0, 0);
|
|
fclose(fp);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
return LA_FINISHED;
|
|
return LA_FINISHED;
|
|
@@ -759,7 +816,7 @@ int ourmod_ImportLayer(laOperator* a, laEvent* e){
|
|
FILE* fp=fopen(a->ConfirmData->StrData,"rb");
|
|
FILE* fp=fopen(a->ConfirmData->StrData,"rb");
|
|
if(!fp) return LA_FINISHED;
|
|
if(!fp) return LA_FINISHED;
|
|
if(!ol) ol=our_NewLayer("Imported");
|
|
if(!ol) ol=our_NewLayer("Imported");
|
|
- our_LayerImportPNG(ol, fp, 0);
|
|
|
|
|
|
+ our_LayerImportPNG(ol, fp, 0, 0, 0, 0, 0);
|
|
fclose(fp);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
return LA_FINISHED;
|
|
return LA_FINISHED;
|
|
@@ -862,6 +919,21 @@ void* ourget_FirstBrush(void* unused, void* unused1){
|
|
void* ourget_our(void* unused, void* unused1){
|
|
void* ourget_our(void* unused, void* unused1){
|
|
return Our;
|
|
return Our;
|
|
}
|
|
}
|
|
|
|
+void ourget_LayerTileStart(OurLayer* l, int* xy){
|
|
|
|
+ our_LayerEnsureImageBuffer(l, 1); xy[0]=Our->ImageX; xy[1]=Our->ImageY+Our->ImageH;
|
|
|
|
+}
|
|
|
|
+void ourset_LayerTileStart(OurLayer* l, int* xy){
|
|
|
|
+ Our->TempLoadX = xy[0]; Our->TempLoadY = xy[1];
|
|
|
|
+}
|
|
|
|
+void* ourget_LayerImage(OurLayer* l, int* r_size, int* r_is_copy){
|
|
|
|
+ void* buf=0;
|
|
|
|
+ if(our_LayerExportPNG(l,0,1,&buf,r_size)){ *r_is_copy=1; return buf; }
|
|
|
|
+ *r_is_copy=0; return buf;
|
|
|
|
+}
|
|
|
|
+void ourset_LayerImage(OurLayer* l, void* data, int size){
|
|
|
|
+ if(!data) return;
|
|
|
|
+ our_LayerImportPNG(l, 0, data, 0, 1, Our->TempLoadX, Our->TempLoadY);
|
|
|
|
+}
|
|
void ourset_LayerMove(OurLayer* l, int move){
|
|
void ourset_LayerMove(OurLayer* l, int move){
|
|
if(move<0 && l->Item.pPrev){ lstMoveUp(&Our->Layers, l); laNotifyUsers("our.canvas.layers"); }
|
|
if(move<0 && l->Item.pPrev){ lstMoveUp(&Our->Layers, l); laNotifyUsers("our.canvas.layers"); }
|
|
elif(move>0 && l->Item.pNext){ lstMoveDown(&Our->Layers, l); laNotifyUsers("our.canvas.layers"); }
|
|
elif(move>0 && l->Item.pNext){ lstMoveDown(&Our->Layers, l); laNotifyUsers("our.canvas.layers"); }
|
|
@@ -888,6 +960,12 @@ void ourset_CanvasSize(void* unused, int* wh){
|
|
void ourset_CanvasPosition(void* unused, int* xy){
|
|
void ourset_CanvasPosition(void* unused, int* xy){
|
|
Our->X=xy[0]; Our->Y=xy[1]; laNotifyUsers("our.canvas");
|
|
Our->X=xy[0]; Our->Y=xy[1]; laNotifyUsers("our.canvas");
|
|
}
|
|
}
|
|
|
|
+void ourset_LayoutPosition(OurLayer* l, int* xy){
|
|
|
|
+ l->OffsetX=xy[0]; l->OffsetY=xy[1]; laNotifyUsers("our.canvas");
|
|
|
|
+}
|
|
|
|
+void ourreset_Canvas(OurPaint* op){
|
|
|
|
+ while(op->Layers.pFirst){ our_RemoveLayer(op->Layers.pFirst); }
|
|
|
|
+}
|
|
|
|
|
|
#define OUR_ADD_PRESSURE_SWITCH(p)\
|
|
#define OUR_ADD_PRESSURE_SWITCH(p)\
|
|
laAddEnumItemAs(p,"NONE","None","Not using pressure",0,0);\
|
|
laAddEnumItemAs(p,"NONE","None","Not using pressure",0,0);\
|
|
@@ -927,7 +1005,7 @@ void ourRegisterEverything(){
|
|
laRegisterUiTemplate("panel_color", "Color", ourui_ColorPanel, 0, 0,0);
|
|
laRegisterUiTemplate("panel_color", "Color", ourui_ColorPanel, 0, 0,0);
|
|
|
|
|
|
pc=laDefineRoot();
|
|
pc=laDefineRoot();
|
|
- laAddSubGroup(pc,"our","Our","OurPaint main","our_paint",0,0,0,-1,ourget_our,0,0,0,0,0,0,0);
|
|
|
|
|
|
+ laAddSubGroup(pc,"our","Our","OurPaint main","our_paint",0,0,0,-1,ourget_our,0,0,0,0,0,0,LA_UDF_SINGLE);
|
|
|
|
|
|
pc=laAddPropertyContainer("our_paint","Our Paint","OurPaint main",0,0,sizeof(OurPaint),0,0,1);
|
|
pc=laAddPropertyContainer("our_paint","Our Paint","OurPaint main",0,0,sizeof(OurPaint),0,0,1);
|
|
laAddSubGroup(pc,"canvas","Canvas","OurPaint canvas","our_canvas",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
|
|
laAddSubGroup(pc,"canvas","Canvas","OurPaint canvas","our_canvas",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
|
|
@@ -964,15 +1042,19 @@ void ourRegisterEverything(){
|
|
laAddOperatorProperty(pc,"remove","Remove","Remove brush","OUR_remove_brush",L'🗴',0);
|
|
laAddOperatorProperty(pc,"remove","Remove","Remove brush","OUR_remove_brush",L'🗴',0);
|
|
|
|
|
|
pc=laAddPropertyContainer("our_canvas","Our Canvas","OurPaint canvas",0,0,sizeof(OurPaint),0,0,1);
|
|
pc=laAddPropertyContainer("our_canvas","Our Canvas","OurPaint canvas",0,0,sizeof(OurPaint),0,0,1);
|
|
|
|
+ laPropContainerExtraFunctions(pc,0,ourreset_Canvas,0,0,0);
|
|
laAddSubGroup(pc,"layers","Layers","Layers","our_layer",0,0,ourui_Layer,offsetof(OurPaint,CurrentLayer),0,0,0,0,0,0,offsetof(OurPaint,Layers),0);
|
|
laAddSubGroup(pc,"layers","Layers","Layers","our_layer",0,0,ourui_Layer,offsetof(OurPaint,CurrentLayer),0,0,0,0,0,0,offsetof(OurPaint,Layers),0);
|
|
laAddSubGroup(pc,"current_layer","Current Layer","Current layer","our_layer",0,0,0,offsetof(OurPaint,CurrentLayer),ourget_FirstLayer,0,laget_ListNext,0,0,0,0,LA_UDF_REFER);
|
|
laAddSubGroup(pc,"current_layer","Current Layer","Current layer","our_layer",0,0,0,offsetof(OurPaint,CurrentLayer),ourget_FirstLayer,0,laget_ListNext,0,0,0,0,LA_UDF_REFER);
|
|
laAddIntProperty(pc,"size","Size","Size of the cropping area",0,"X,Y","px",0,0,0,2400,0,offsetof(OurPaint,W),0,0,2,0,0,0,0,ourset_CanvasSize,0,0,0);
|
|
laAddIntProperty(pc,"size","Size","Size of the cropping area",0,"X,Y","px",0,0,0,2400,0,offsetof(OurPaint,W),0,0,2,0,0,0,0,ourset_CanvasSize,0,0,0);
|
|
laAddIntProperty(pc,"position","Position","Position of the cropping area",0,"X,Y","px",0,0,0,2400,0,offsetof(OurPaint,X),0,0,2,0,0,0,0,ourset_CanvasPosition,0,0,0);
|
|
laAddIntProperty(pc,"position","Position","Position of the cropping area",0,"X,Y","px",0,0,0,2400,0,offsetof(OurPaint,X),0,0,2,0,0,0,0,ourset_CanvasPosition,0,0,0);
|
|
|
|
|
|
- pc=laAddPropertyContainer("our_layer","Our Layer","OurPaint layer",0,0,sizeof(OurLayer),0,0,1);
|
|
|
|
|
|
+ pc=laAddPropertyContainer("our_layer","Our Layer","OurPaint layer",0,0,sizeof(OurLayer),0,0,2);
|
|
|
|
+ laPropContainerExtraFunctions(pc,ourbeforefree_Layer,ourbeforefree_Layer,0,0,0);
|
|
laAddStringProperty(pc,"name","Name","Name of the layer",0,0,0,0,1,offsetof(OurLayer,Name),0,0,0,0,LA_AS_IDENTIFIER);
|
|
laAddStringProperty(pc,"name","Name","Name of the layer",0,0,0,0,1,offsetof(OurLayer,Name),0,0,0,0,LA_AS_IDENTIFIER);
|
|
laAddIntProperty(pc,"__move","Move Slider","Move Slider",LA_WIDGET_HEIGHT_ADJUSTER,0,0,0,0,0,0,0,0,0,ourset_LayerMove,0,0,0,0,0,0,0,0,0);
|
|
laAddIntProperty(pc,"__move","Move Slider","Move Slider",LA_WIDGET_HEIGHT_ADJUSTER,0,0,0,0,0,0,0,0,0,ourset_LayerMove,0,0,0,0,0,0,0,0,0);
|
|
- //laAddSubGroup(pc,"Rows","Rows","Rows of tiles","our_rows",0,0,0,0,0,0,0,0,0,0,offsetof(OurLayer,Rows),0);
|
|
|
|
|
|
+ laAddIntProperty(pc,"offset","Offset","Offset of the layer",0,"X,Y","px",0,0,0,0,0,offsetof(OurLayer,OffsetX),0,0,2,0,0,0,0,ourset_LayoutPosition,0,0,0);
|
|
|
|
+ laAddIntProperty(pc,"tile_start","Tile Start","Tile starting position for loading",0,0,0,0,0,0,0,0,0,0,0,2,0,0,ourget_LayerTileStart,0,ourset_LayerTileStart,0,0,LA_UDF_ONLY);
|
|
|
|
+ laAddRawProperty(pc,"image","Image","The image data of this tile",0,0,ourget_LayerImage,ourset_LayerImage,LA_UDF_ONLY);
|
|
laAddOperatorProperty(pc,"move","Move","Move Layer","OUR_move_layer",0,0);
|
|
laAddOperatorProperty(pc,"move","Move","Move Layer","OUR_move_layer",0,0);
|
|
laAddOperatorProperty(pc,"remove","Remove","Remove layer","OUR_remove_layer",L'🗴',0);
|
|
laAddOperatorProperty(pc,"remove","Remove","Remove layer","OUR_remove_layer",L'🗴',0);
|
|
|
|
|
|
@@ -987,6 +1069,8 @@ void ourRegisterEverything(){
|
|
laAssignNewKey(km, 0, "OUR_pick", LA_KM_SEL_UI_EXTRA, 0, LA_R_MOUSE_DOWN, 0, 0);
|
|
laAssignNewKey(km, 0, "OUR_pick", LA_KM_SEL_UI_EXTRA, 0, LA_R_MOUSE_DOWN, 0, 0);
|
|
|
|
|
|
laSetMenuBarTemplates(ourui_MenuButtons, laui_DefaultMenuExtras, "OurPaint v0.1");
|
|
laSetMenuBarTemplates(ourui_MenuButtons, laui_DefaultMenuExtras, "OurPaint v0.1");
|
|
|
|
+
|
|
|
|
+ laSaveProp("our");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|