*/}}
Browse Source

Preliminary proofing UI

YimingWu 2 weeks ago
parent
commit
f18607015d

+ 2 - 0
CMakeLists.txt

@@ -22,6 +22,7 @@ if(NOT (${LAGUI_ANDROID}))
     find_package(X11 REQUIRED)
     find_package(X11 REQUIRED)
     find_package(Freetype REQUIRED)
     find_package(Freetype REQUIRED)
     find_package(GLEW REQUIRED)
     find_package(GLEW REQUIRED)
+    find_package(LCMS2 REQUIRED)
     find_package(LuaJIT)
     find_package(LuaJIT)
     find_package(PNG)
     find_package(PNG)
 endif()
 endif()
@@ -158,4 +159,5 @@ install(TARGETS lagui EXPORT lagui-targets DESTINATION lib/lagui)
 install(EXPORT lagui-targets DESTINATION lib/lagui)
 install(EXPORT lagui-targets DESTINATION lib/lagui)
 install(FILES lagui-config.cmake DESTINATION lib/lagui)
 install(FILES lagui-config.cmake DESTINATION lib/lagui)
 install(FILES FindLuaJIT.cmake DESTINATION lib/lagui)
 install(FILES FindLuaJIT.cmake DESTINATION lib/lagui)
+install(FILES FindLCMS2.cmake DESTINATION lib/lagui)
 install(FILES ${LAGUI_FONTS} DESTINATION ${LAGUI_FONT_CUSTOM_PATH})
 install(FILES ${LAGUI_FONTS} DESTINATION ${LAGUI_FONT_CUSTOM_PATH})

+ 17 - 0
FindLCMS2.cmake

@@ -0,0 +1,17 @@
+find_path(LCMS2_INCLUDE_DIR lcms2.h PATHS /usr/include /usr/local/include /opt/include /opt/local/include)
+
+set(LCMS2_NAMES ${LCMS2_NAMES} lcms2 liblcms2 liblcms2_static)
+
+find_library(LCMS2_LIBRARY NAMES ${LCMS2_NAMES} )
+
+mark_as_advanced(LCMS2_INCLUDE_DIR LCMS2_LIBRARY)
+
+# handle the QUIETLY and REQUIRED arguments and set LCMS2_FOUND to TRUE if
+# all listed variables are TRUE
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LCMS2  DEFAULT_MSG  LCMS2_LIBRARY  LCMS2_INCLUDE_DIR)
+
+if(LCMS2_FOUND)
+  set( LCMS2_INCLUDE_DIRS ${LCMS2_INCLUDE_DIR})
+  set( LCMS2_LIBRARIES ${LCMS2_LIBRARY} )
+endif()

+ 0 - 3
la_data.c

@@ -2039,9 +2039,6 @@ void laSetActiveInstance(laProp *sub, void *FromInstance, void *Instance){
             laNotifySubPropUsers(sp, FromInstance);
             laNotifySubPropUsers(sp, FromInstance);
             sp->Set(FromInstance, Instance);
             sp->Set(FromInstance, Instance);
         }
         }
-        if(sub->OffsetIsPointer && sub->Offset==0){
-            printf("where did that come from\n");
-        }
         if (sub->OffsetIsPointer && sub->Offset>=0){
         if (sub->OffsetIsPointer && sub->Offset>=0){
             void **a = (void **)((BYTE *)FromInstance + sub->Offset);
             void **a = (void **)((BYTE *)FromInstance + sub->Offset);
             laNotifySubPropUsers(sp, FromInstance);
             laNotifySubPropUsers(sp, FromInstance);

+ 10 - 0
la_interface.h

@@ -336,6 +336,14 @@ STRUCTURE(laProgressDisplay){
     int Called,Shown;
     int Called,Shown;
 };
 };
 
 
+STRUCTURE(laProofingLUT){
+    laListItem Item;
+    laSafeString* Name;
+    uint8_t* TablesRGB; // 33 points
+    uint8_t* TableClay; // 33 points
+    uint8_t* TableD65P3; // 33 points
+};
+
 STRUCTURE(laInitArguments){
 STRUCTURE(laInitArguments){
     int GLMajor,GLMinor,BufferSamples;
     int GLMajor,GLMinor,BufferSamples;
     int GLESMajor,GLESMinor;
     int GLESMajor,GLESMinor;
@@ -356,6 +364,7 @@ NEED_STRUCTURE(laInputMappingBundle);
 
 
 #define LA_LUT_PRECISION 33
 #define LA_LUT_PRECISION 33
 #define LA_LUT_PIXCOUNT (LA_LUT_PRECISION * LA_LUT_PRECISION * LA_LUT_PRECISION)
 #define LA_LUT_PIXCOUNT (LA_LUT_PRECISION * LA_LUT_PRECISION * LA_LUT_PRECISION)
+#define LA_LUT_VAL (LA_LUT_PRECISION-1)
 
 
 STRUCTURE(LA){
 STRUCTURE(LA){
     laListItem Hyper;
     laListItem Hyper;
@@ -384,6 +393,7 @@ STRUCTURE(LA){
     laListHandle Windows;
     laListHandle Windows;
     laListHandle WastedPanels;
     laListHandle WastedPanels;
     laListHandle Screens;
     laListHandle Screens;
+    laListHandle ProofingLUTs;
     int AutoSwitchColorSpace;
     int AutoSwitchColorSpace;
 
 
     laConfirmData *InvokeConfirmData;
     laConfirmData *InvokeConfirmData;

+ 8 - 3
la_kernel.c

@@ -1024,6 +1024,10 @@ void la_InitProgressWindow(){
 #endif
 #endif
 }
 }
 
 
+void la_InitProofingLut(){
+
+}
+
 void laSetFontFolderPath(char* absolute){
 void laSetFontFolderPath(char* absolute){
     strcpy(MAIN.SysFontDir,absolute); int len=strlen(MAIN.SysFontDir);
     strcpy(MAIN.SysFontDir,absolute); int len=strlen(MAIN.SysFontDir);
     if(MAIN.SysFontDir[len-1]!='/'){ MAIN.SysFontDir[len]='/'; MAIN.SysFontDir[len+1]=0; }
     if(MAIN.SysFontDir[len-1]!='/'){ MAIN.SysFontDir[len]='/'; MAIN.SysFontDir[len+1]=0; }
@@ -1451,9 +1455,9 @@ int laGetReadyWith(laInitArguments* ia){
 
 
     if(MAIN.InitArgs.EnableLogStdOut){ MAIN.EnableLogStdOut=1; }
     if(MAIN.InitArgs.EnableLogStdOut){ MAIN.EnableLogStdOut=1; }
 
 
-    laSetProofingLut(DATA_LUT_PROOF_SRGB, 0);
-    laSetProofingLut(DATA_LUT_PROOF_CLAY, 1);
-    laSetProofingLut(DATA_LUT_PROOF_D65P3, 2);
+    //laSetProofingLut(DATA_LUT_PROOF_SRGB, 0);
+    //laSetProofingLut(DATA_LUT_PROOF_CLAY, 1);
+    //laSetProofingLut(DATA_LUT_PROOF_D65P3, 2);
 
 
     logPrintNew("Initialization Completed\n");
     logPrintNew("Initialization Completed\n");
     MAIN.InitDone=1;
     MAIN.InitDone=1;
@@ -2387,6 +2391,7 @@ void la_RefreshProofingLut(){
     tnsEnableShaderv(T->immShader);
     tnsEnableShaderv(T->immShader);
     tnsShader* s = T->immShader;
     tnsShader* s = T->immShader;
     if(!MAIN.ProofingLUT[table] || !MAIN.CurrentWindow->OutputProofing){
     if(!MAIN.ProofingLUT[table] || !MAIN.CurrentWindow->OutputProofing){
+        if(!MAIN.ProofingLUT[table]){ MAIN.CurrentWindow->OutputProofing=0; }
         return;
         return;
     }
     }
 
 

+ 5 - 0
lagui-config.cmake

@@ -22,6 +22,7 @@ find_package(OpenGL REQUIRED)
 find_package(X11 REQUIRED)
 find_package(X11 REQUIRED)
 find_package(Freetype REQUIRED)
 find_package(Freetype REQUIRED)
 find_package(GLEW REQUIRED)
 find_package(GLEW REQUIRED)
+find_package(LCMS2 REQUIRED)
 find_package(PNG)
 find_package(PNG)
 find_package(LuaJIT)
 find_package(LuaJIT)
 
 
@@ -47,6 +48,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux")
         ${GLEW_LIBRARIES}
         ${GLEW_LIBRARIES}
         ${LAGUI_GL_LIB}
         ${LAGUI_GL_LIB}
         ${FREETYPE_LIBRARIES}
         ${FREETYPE_LIBRARIES}
+        ${LCMS2_LIBRARIES}
         ${X11_Xfixes_LIB}
         ${X11_Xfixes_LIB}
         ${X11_Xrandr_LIB}
         ${X11_Xrandr_LIB}
         m X11 Xi Xcursor
         m X11 Xi Xcursor
@@ -62,6 +64,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux")
         ${X11_INCLUDE_DIR}
         ${X11_INCLUDE_DIR}
         ${GLEW_INCLUDE_PATH}
         ${GLEW_INCLUDE_PATH}
         ${FREETYPE_INCLUDE_DIRS}
         ${FREETYPE_INCLUDE_DIRS}
+        ${LCMS2_INCLUDE_DIR}
         ${LAGUI_INCLUDE_DIRS}
         ${LAGUI_INCLUDE_DIRS}
         CACHE INTERNAL "Include dirs of LaGUI and dependencies"
         CACHE INTERNAL "Include dirs of LaGUI and dependencies"
     )
     )
@@ -79,6 +82,7 @@ elseif (CMAKE_SYSTEM_NAME MATCHES "Windows")
         ${OPENGL_LIBRARY}
         ${OPENGL_LIBRARY}
         ${FREETYPE_LIBRARIES}
         ${FREETYPE_LIBRARIES}
         ${CMAKE_DL_LIBS}
         ${CMAKE_DL_LIBS}
+        ${LCMS2_LIBRARIES}
         Threads::Threads
         Threads::Threads
         lagui shlwapi Shcore Imm32
         lagui shlwapi Shcore Imm32
         CACHE INTERNAL "LaGUI shared libs"
         CACHE INTERNAL "LaGUI shared libs"
@@ -87,6 +91,7 @@ elseif (CMAKE_SYSTEM_NAME MATCHES "Windows")
         ${CMAKE_SOURCE_DIR}
         ${CMAKE_SOURCE_DIR}
         ${GLEW_INCLUDE_PATH}
         ${GLEW_INCLUDE_PATH}
         ${FREETYPE_INCLUDE_DIRS}
         ${FREETYPE_INCLUDE_DIRS}
+        ${LCMS2_INCLUDE_DIR}
         ${LAGUI_INCLUDE_DIRS}
         ${LAGUI_INCLUDE_DIRS}
         CACHE INTERNAL "Include dirs of LaGUI and dependencies"
         CACHE INTERNAL "Include dirs of LaGUI and dependencies"
     )
     )

+ 107 - 1
resources/la_operators.c

@@ -17,6 +17,7 @@
 */
 */
 
 
 #include "../la_5.h"
 #include "../la_5.h"
+#include "lcms2.h"
 
 
 extern LA MAIN;
 extern LA MAIN;
 extern struct _tnsMain *T;
 extern struct _tnsMain *T;
@@ -2644,7 +2645,6 @@ int OPINV_RemoveScreenConfig(laOperator *a, laEvent *e){
     laEnableYesNoPanel(a, 0, "Confirm?", "Will remove this screen entry", e->x, e->y, 200, e);
     laEnableYesNoPanel(a, 0, "Confirm?", "Will remove this screen entry", e->x, e->y, 200, e);
     return LA_RUNNING;
     return LA_RUNNING;
 }
 }
-
 int OPMOD_RemoveScreenConfig(laOperator *a, laEvent *e){
 int OPMOD_RemoveScreenConfig(laOperator *a, laEvent *e){
     if(!a->This || !a->This->EndInstance) return LA_FINISHED; laScreen* s=a->This->EndInstance;
     if(!a->This || !a->This->EndInstance) return LA_FINISHED; laScreen* s=a->This->EndInstance;
     if(a->ConfirmData){
     if(a->ConfirmData){
@@ -2656,6 +2656,109 @@ int OPMOD_RemoveScreenConfig(laOperator *a, laEvent *e){
     return LA_FINISHED;
     return LA_FINISHED;
 }
 }
 
 
+static cmsHPROFILE la_CreateProfileClay(){
+    cmsToneCurve* Gamma[3]; cmsHPROFILE hProfile; cmsCIExyY D65;
+    cmsCIExyYTRIPLE Primaries = { {0.64, 0.33, 1 }, {0.21, 0.71, 1 }, {0.15, 0.06, 1 } };
+    Gamma[0] = Gamma[1] = Gamma[2] = cmsBuildGamma(0, 2.19921875);
+    cmsWhitePointFromTemp(&D65, 6504);
+    hProfile = cmsCreateRGBProfile(&D65, &Primaries, Gamma);
+    cmsFreeToneCurve(Gamma[0]);
+    return hProfile;
+}
+static cmsHPROFILE la_CreateProfileD65P3(){
+    cmsToneCurve* Gamma[3]; cmsHPROFILE hProfile; cmsCIExyY D65;
+    cmsCIExyYTRIPLE Primaries = { {0.680,0.320,1.0}, {0.265,0.690,1.0}, {0.150,0.060,1.0} };
+    cmsFloat64Number srgb_parameters[5] = { 2.4, 1.0 / 1.055,  0.055 / 1.055, 1.0 / 12.92, 0.04045 };
+    Gamma[0] = Gamma[1] = Gamma[2] = cmsBuildParametricToneCurve(NULL, 4, srgb_parameters);
+    cmsWhitePointFromTemp(&D65, 6504);
+    hProfile = cmsCreateRGBProfile(&D65, &Primaries, Gamma);
+    cmsFreeToneCurve(Gamma[0]);
+    return hProfile;
+}
+static int la_InitProofLUT(void** lut, cmsHPROFILE cmyk_profile, cmsHPROFILE rgb_profile){
+    cmsHTRANSFORM htransform=cmsCreateProofingTransform(rgb_profile,TYPE_RGB_DBL,rgb_profile,TYPE_RGB_8,cmyk_profile,
+        INTENT_ABSOLUTE_COLORIMETRIC,INTENT_ABSOLUTE_COLORIMETRIC,cmsFLAGS_HIGHRESPRECALC|cmsFLAGS_SOFTPROOFING|cmsFLAGS_NOOPTIMIZE);
+    if(!htransform){ (*lut)=0; return 0; }
+    real data[LA_LUT_PIXCOUNT*3];
+    real cmyk8[LA_LUT_PIXCOUNT*4];
+    int prec=LA_LUT_PRECISION;
+    for(int i=0;i<prec;i++){
+        int counti=i*prec*prec;
+        for(int j=0;j<prec;j++){
+            int countj=j*prec;
+            for(int k=0;k<prec;k++){
+                real* p=&data[(counti+countj+k)*3];
+                p[0]=((real)i)/LA_LUT_VAL; p[1]=((real)j)/LA_LUT_VAL; p[2]=((real)k)/LA_LUT_VAL;
+            }
+        }
+    }
+
+    *lut=malloc(sizeof(char)*3*LA_LUT_PIXCOUNT);
+    char* table = *lut;
+    cmsDoTransform(htransform,data,table,LA_LUT_PIXCOUNT);
+}
+static int la_LoadProofingICC(char* path){
+    cmsHPROFILE cmyk = cmsOpenProfileFromFile(path,"r");
+    cmsHPROFILE srgb = cmsCreate_sRGBProfile();
+    cmsHPROFILE clay = la_CreateProfileClay();
+    cmsHPROFILE d65p3 = la_CreateProfileD65P3();
+    char* lut1,*lut2,*lut3;
+    la_InitProofLUT(&lut1,cmyk,srgb); if(!lut1){ return 0; }
+    la_InitProofLUT(&lut2,cmyk,srgb); if(!lut2){ free(lut1); return 0; }
+    la_InitProofLUT(&lut3,cmyk,srgb); if(!lut3){ free(lut1);free(lut2); return 0; }
+
+    laProofingLUT *pl=memAcquire(sizeof(laProofingLUT));
+    char* name=strGetLastSegment(path,LA_PATH_SEP);
+    strSafeSet(&pl->Name,name);
+    pl->TablesRGB=lut1; pl->TableClay=lut2; pl->TableD65P3=lut3;
+
+    laSetProofingLut(lut1,0); laSetProofingLut(lut2,1); laSetProofingLut(lut3,2);
+
+    lstAppendItem(&MAIN.ProofingLUTs,pl);
+    return 1;
+}
+static void la_RemoveProofingProfile(laProofingLUT* pl){
+    laProofingLUT* npl=pl->Item.pNext?pl->Item.pNext:pl->Item.pPrev;
+    free(pl->TablesRGB); free(pl->TableClay); free(pl->TableD65P3);
+    strSafeDestroy(&pl->Name); lstRemoveItem(&MAIN.ProofingLUTs,pl); memFree(pl);
+    if(npl){
+        laSetProofingLut(npl->TablesRGB,0); laSetProofingLut(npl->TableClay,1); laSetProofingLut(npl->TableD65P3,2);
+    }else{
+        laSetProofingLut(0,0); laSetProofingLut(0,1); laSetProofingLut(0,2);
+    }
+}
+int OPINV_NewProofingLUT(laOperator *a, laEvent *e){
+    laInvoke(a, "LA_file_dialog", e, 0, "filter_extensions=icc;use_extension=icc", 0);
+    return LA_RUNNING;
+}
+int OPMOD_NewProofingLUT(laOperator *a, laEvent *e){
+    if(a->ConfirmData){
+        if(a->ConfirmData->Mode==LA_CONFIRM_OK){
+            if(a->ConfirmData->StrData){
+                if(!la_LoadProofingICC(a->ConfirmData->StrData)){
+                    laEnableMessagePanel(a,0,"Error","Could not load this color profile to use for proofing.",e->x,e->y,LA_RH*15,e);
+                }
+            }
+        }
+        return LA_FINISHED;
+    }
+    return LA_RUNNING;
+}
+int OPINV_RemoveProofingLUT(laOperator *a, laEvent *e){
+    if(!a->This || !a->This->EndInstance) return LA_FINISHED;
+    laEnableYesNoPanel(a, 0, "Confirm?", "Will remove this profile", e->x, e->y, 200, e);
+    return LA_RUNNING;
+}
+int OPMOD_RemoveProofingLUT(laOperator *a, laEvent *e){
+    if(!a->This || !a->This->EndInstance) return LA_FINISHED; laProofingLUT* pl=a->This->EndInstance;
+    if(a->ConfirmData){
+        if(a->ConfirmData->Mode == LA_CONFIRM_OK){
+            la_RemoveProofingProfile(pl); laNotifyUsers("la.user_preferences.proofing_profiles");
+        }
+        return LA_FINISHED;
+    }
+    return LA_FINISHED;
+}
 
 
 int OPINV_OpenInternetLink(laOperator *a, laEvent *e){
 int OPINV_OpenInternetLink(laOperator *a, laEvent *e){
     char *link = strGetArgumentString(a->ExtraInstructionsP, "link");
     char *link = strGetArgumentString(a->ExtraInstructionsP, "link");
@@ -2894,4 +2997,7 @@ void la_RegisterBuiltinOperators(){
     
     
     laCreateOperatorType("LA_delete_theme", "Delete Theme", "Delete a theme", 0, 0, 0, OPINV_DeleteTheme, OPMOD_DeleteTheme, U'🞫', LA_ACTUATOR_SYSTEM);
     laCreateOperatorType("LA_delete_theme", "Delete Theme", "Delete a theme", 0, 0, 0, OPINV_DeleteTheme, OPMOD_DeleteTheme, U'🞫', LA_ACTUATOR_SYSTEM);
     laCreateOperatorType("LA_new_theme", "New Theme", "Create a new theme", 0, 0, 0, OPINV_NewTheme, 0, U'🞧', LA_ACTUATOR_SYSTEM);
     laCreateOperatorType("LA_new_theme", "New Theme", "Create a new theme", 0, 0, 0, OPINV_NewTheme, 0, U'🞧', LA_ACTUATOR_SYSTEM);
+
+    laCreateOperatorType("LA_new_proofing_profile", "New Proofing Profile", "Load an CMYK type icc color profile for soft proofing", 0, 0, 0, OPINV_NewProofingLUT, OPMOD_NewProofingLUT, U'🞧', LA_ACTUATOR_SYSTEM);
+    laCreateOperatorType("LA_remove_proofing_profile", "Remove Proofing Profile", "Remove this proofing profile", 0, 0, 0, OPINV_RemoveProofingLUT, OPMOD_RemoveProofingLUT, U'🞫', LA_ACTUATOR_SYSTEM);
 }
 }

+ 49 - 0
resources/la_properties.c

@@ -1141,6 +1141,45 @@ int laaction_VerifyRootObject(void* Parent, laPropContainer* ParentType, void* C
     return 0;
     return 0;
 }
 }
 
 
+
+void* lagetraw_ProofingData(laProofingLUT* pl, int* r_size, int* ret_is_copy){
+    int single_size=LA_LUT_PIXCOUNT*3;
+    *r_size=3*sizeof(char)*single_size; // 3x rgb x pixcount
+    *ret_is_copy=1;
+    void* data=malloc(*r_size);
+    memcpy(data,pl->TablesRGB,single_size);
+    memcpy(&data[single_size],pl->TableClay,single_size);
+    memcpy(&data[single_size*2],pl->TableD65P3,single_size);
+    return data;
+}
+void lasetraw_ProofingData(laProofingLUT* pl, void* data, int DataSize){
+    int single_size=LA_LUT_PIXCOUNT*3; if(DataSize<single_size*3) return;
+    if(!pl->TablesRGB)pl->TablesRGB=malloc(single_size);   memcpy(pl->TablesRGB,data,single_size);
+    if(!pl->TableClay)pl->TableClay=malloc(single_size);   memcpy(pl->TableClay,&data[single_size],single_size);
+    if(!pl->TableD65P3)pl->TableD65P3=malloc(single_size); memcpy(pl->TableD65P3,&data[single_size*2],single_size);
+}
+void laset_ActiveProofingProfile(void* unused, laProofingLUT* pl){
+    if(!pl->TablesRGB || !pl->TableD65P3 || !pl->TableClay){ return; }
+    laSetProofingLut(pl->TablesRGB,0); laSetProofingLut(pl->TableClay,1); laSetProofingLut(pl->TableD65P3,2);
+}
+int lagetstate_ProofingProfile(laProofingLUT* pl){
+    if(pl->TablesRGB==MAIN.ProofingLUT[0]) return 1; return -1;
+}
+void laset_ProofingProfileMove(laProofingLUT* pl, int move){
+    if(move<0 && pl->Item.pPrev){ lstMoveUp(&MAIN.ProofingLUTs, pl); laNotifyUsers("la.user_preferences.proofing_profiles"); }
+    elif(move>0 && pl->Item.pNext){ lstMoveDown(&MAIN.ProofingLUTs, pl); laNotifyUsers("la.user_preferences.proofing_profiles"); }
+}
+int laget_CurrentProofingID(void* unused){
+    int i=0; for(laProofingLUT* pl=MAIN.ProofingLUTs.pFirst;pl;pl=pl->Item.pNext){ if(pl->TablesRGB==MAIN.ProofingLUT[0]) break; i++; }
+    return i;
+}
+void laset_CurrentProofingID(void* unused, int id){
+    laProofingLUT* pl=MAIN.ProofingLUTs.pFirst; for(int i=0;i<id && pl;i++){ if(pl->TablesRGB==MAIN.ProofingLUT[0]) break; pl=pl->Item.pNext; }
+    if(!pl) return;
+    laSetProofingLut(pl->TablesRGB,0); laSetProofingLut(pl->TableClay,1); laSetProofingLut(pl->TableD65P3,2);
+}
+
+
 void lareset_Main(void* Unused){
 void lareset_Main(void* Unused){
     return;
     return;
 }
 }
@@ -1835,6 +1874,9 @@ void la_RegisterInternalProps(){
             laAddEnumItemAs(ep, "NONE", "None", "Do not do color management on the window", 0, 0);
             laAddEnumItemAs(ep, "NONE", "None", "Do not do color management on the window", 0, 0);
             laAddEnumItemAs(ep, "ENABLED", "Enabled", "Enable color management on the window", 1, 0);
             laAddEnumItemAs(ep, "ENABLED", "Enabled", "Enable color management on the window", 1, 0);
 
 
+            laAddSubGroup(p,"proofing_profiles","Proofing Profiles","Soft proofing color profiles","la_proofing_profile",0,0,0,-1,0,0,0,laset_ActiveProofingProfile,lagetstate_ProofingProfile,0,offsetof(LA,ProofingLUTs),0);
+            laAddIntProperty(p,"current_proofing_id","Current Proofing ID","Current soft proofing id in the list",0,0,0,0,0,0,0,0,-1,laget_CurrentProofingID,laset_CurrentProofingID,0,0,0,0,0,0,0,0,0);
+
             laAddFloatProperty(p, "margin_size", "Margin Size", "The global margin factor", 0,0,0,2.0f, 0.1f, 0.02, 1.0f, 0,offsetof(LA, MarginSize), 0,laset_MarginSize, 0,0,0,0,0,0,0,0,0);
             laAddFloatProperty(p, "margin_size", "Margin Size", "The global margin factor", 0,0,0,2.0f, 0.1f, 0.02, 1.0f, 0,offsetof(LA, MarginSize), 0,laset_MarginSize, 0,0,0,0,0,0,0,0,0);
             laAddFloatProperty(p, "font_size", "Font Size", "The height of the font related to the row height", 0,0,0,1.0f, 0.1f, 0.02, 0.75, 0,offsetof(LA, FontSize), 0,laset_FontSize, 0,0,0,0,0,0,0,0,0);
             laAddFloatProperty(p, "font_size", "Font Size", "The height of the font related to the row height", 0,0,0,1.0f, 0.1f, 0.02, 0.75, 0,offsetof(LA, FontSize), 0,laset_FontSize, 0,0,0,0,0,0,0,0,0);
             laAddIntProperty(p, "interface_size", "Interface Size", "The height of one row of ui item", 0,0,0,64, 16, 1, 40,0,offsetof(LA, UiRowHeight), 0,laset_UiRowHeight, 0,0,0,0,0,0,0,0,0);
             laAddIntProperty(p, "interface_size", "Interface Size", "The height of one row of ui item", 0,0,0,64, 16, 1, 40,0,offsetof(LA, UiRowHeight), 0,laset_UiRowHeight, 0,0,0,0,0,0,0,0,0);
@@ -1884,6 +1926,13 @@ void la_RegisterInternalProps(){
             }
             }
         }
         }
 
 
+        p = laAddPropertyContainer("la_proofing_profile", "Poofing Profile", "Profile for soft proofing", 0,0,sizeof(laProofingLUT), 0,0,1);{
+            laAddIntProperty(p,"__move","Move Slider","Move Slider",LA_WIDGET_HEIGHT_ADJUSTER,0,0,0,0,0,0,0,0,0,laset_ProofingProfileMove,0,0,0,0,0,0,0,0,LA_UDF_IGNORE);
+            laAddStringProperty(p,"name","Name","Name of the profile",0,0,0,0,1,offsetof(laProofingLUT,Name),0,0,0,0,0);
+            laAddRawProperty(p,"raw_data","Raw Data","Raw data representing the lut",-1,0,lagetraw_ProofingData,lasetraw_ProofingData,0); 
+            laAddOperatorProperty(p,"remove","Remove","Remove this proofing profile","LA_remove_proofing_profile",0,0);
+        }
+
         p = laAddPropertyContainer("la_input_mapping_bundle", "Input Mapping Bundle", "Bundle of input mapping data", 0,0,sizeof(laInputMappingBundle), 0,0,1);{
         p = laAddPropertyContainer("la_input_mapping_bundle", "Input Mapping Bundle", "Bundle of input mapping data", 0,0,sizeof(laInputMappingBundle), 0,0,1);{
             laAddSubGroup(p, "mappings","Mappings","Input mappings","la_input_mapping",0,0,0,-1,0,laget_CurrentInputMapping,0,0,0,0,offsetof(laInputMappingBundle,InputMappings),0);
             laAddSubGroup(p, "mappings","Mappings","Input mappings","la_input_mapping",0,0,0,-1,0,laget_CurrentInputMapping,0,0,0,0,offsetof(laInputMappingBundle,InputMappings),0);
             laAddSubGroup(p, "current","Current Mapping","Current input mapping","la_input_mapping",0,0,0,offsetof(laInputMappingBundle,CurrentInputMapping),laget_FirstInputMapping,0,laget_ListNext,0,0,0,0,LA_UDF_REFER);
             laAddSubGroup(p, "current","Current Mapping","Current input mapping","la_input_mapping",0,0,0,offsetof(laInputMappingBundle,CurrentInputMapping),laget_FirstInputMapping,0,laget_ListNext,0,0,0,0,LA_UDF_REFER);

+ 42 - 7
resources/la_templates.c

@@ -621,7 +621,13 @@ void laui_DefaultMenuBarActual(laUiList *uil, laPropPack *pp, laPropPack *actins
                 }laEndCondition(uil, uc1);
                 }laEndCondition(uil, uc1);
 #endif
 #endif
                 laShowItemFull(uil,c,0,"la.windows.output_show_overflow",0,"text=🟩;",0,0)->Flags|=LA_UI_FLAGS_NO_CONFIRM;
                 laShowItemFull(uil,c,0,"la.windows.output_show_overflow",0,"text=🟩;",0,0)->Flags|=LA_UI_FLAGS_NO_CONFIRM;
-                laShowItemFull(uil,c,0,"la.windows.output_proofing",0,0,0,0)->Flags|=LA_UI_FLAGS_CYCLE|LA_UI_FLAGS_ICON|LA_UI_FLAGS_HIGHLIGHT|LA_UI_FLAGS_NO_CONFIRM;
+                laUiItem* hasproof=laOnConditionThat(uil,c,laPropExpression(0,"la.user_preferences.proofing_profiles"));{
+                    laUiItem* proofbtn=laShowItemFull(uil,c,0,"la.windows.output_proofing",0,"icon=🖶",0,0);
+                        proofbtn->Flags|=LA_UI_FLAGS_CYCLE|LA_UI_FLAGS_ICON|LA_UI_FLAGS_HIGHLIGHT|LA_UI_FLAGS_NO_CONFIRM;
+                    //laUiItem* enproof=laOnConditionThat(uil,c,laPropExpression(&proofbtn->PP,""));{
+                    //    Should show a name here.
+                    //}laEndCondition(uil,enproof);
+                }laEndCondition(uil,hasproof);
                 laShowItemFull(uil,c,0,"la.windows.use_composing",0,"text=☀",0,0)->Flags|=LA_UI_FLAGS_NO_CONFIRM;
                 laShowItemFull(uil,c,0,"la.windows.use_composing",0,"text=☀",0,0)->Flags|=LA_UI_FLAGS_NO_CONFIRM;
                 laUiItem* cmp=laOnConditionThat(uil,c,laPropExpression(0,"la.windows.use_composing"));{
                 laUiItem* cmp=laOnConditionThat(uil,c,laPropExpression(0,"la.windows.use_composing"));{
                     muil = laMakeMenuPageEx(uil, c, "⯆",LA_UI_FLAGS_NO_CONFIRM);{ mc = laFirstColumn(muil);
                     muil = laMakeMenuPageEx(uil, c, "⯆",LA_UI_FLAGS_NO_CONFIRM);{ mc = laFirstColumn(muil);
@@ -1355,6 +1361,19 @@ void laui_Screen(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *U
     laShowItem(uil,cr,This,"description");
     laShowItem(uil,cr,This,"description");
     laEndCondition(uil,b);
     laEndCondition(uil,b);
 }
 }
+void laui_ProofingProfile(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
+    laColumn* c=laFirstColumn(uil); laSplitColumn(uil,c,0.25); laColumn*cl,*cr; cl=laLeftColumn(c,1); cr=laRightColumn(c,0);
+
+    laShowItem(uil,cl,This,"__move");
+    laUiItem* b=laBeginRow(uil,cr,0,0);
+    laUiItem* bb=laOnConditionToggle(uil,cr,0,0,0,0,0);{ strSafeSet(&bb->ExtraInstructions,"icon=🖉;");
+        laShowItem(uil,cr,This,"name")->Expand=1;
+    }laElse(uil,bb);{
+        laShowItemFull(uil,cr,This,"name",LA_WIDGET_STRING_PLAIN,0,0,0)->Expand=1;
+    }laEndCondition(uil,bb);
+    laShowItem(uil,cr,This,"remove")->Flags|=LA_UI_FLAGS_ICON;
+    laEndRow(uil,b);
+}
 
 
 void laui_UserPreference(laUiList *uil, laPropPack *Base, laPropPack *OperatorInst, laColumn *ExtraColumns, int context){
 void laui_UserPreference(laUiList *uil, laPropPack *Base, laPropPack *OperatorInst, laColumn *ExtraColumns, int context){
     laColumn* c = laFirstColumn(uil),*cl,*cr; laSplitColumn(uil,c,0.5);cl=laLeftColumn(c,0);cr=laRightColumn(c,0);
     laColumn* c = laFirstColumn(uil),*cl,*cr; laSplitColumn(uil,c,0.5);cl=laLeftColumn(c,0);cr=laRightColumn(c,0);
@@ -1416,17 +1435,33 @@ void laui_UserPreference(laUiList *uil, laPropPack *Base, laPropPack *OperatorIn
             laShowItem(muil, mcr, &UP->PP, "color_picker_gamma");
             laShowItem(muil, mcr, &UP->PP, "color_picker_gamma");
             laShowItem(muil, mcr, &UP->PP, "enable_color_management")->Flags|=LA_UI_FLAGS_CHECKBOX;
             laShowItem(muil, mcr, &UP->PP, "enable_color_management")->Flags|=LA_UI_FLAGS_CHECKBOX;
 
 
-#ifndef LAGUI_ANDROID
             laUiItem* bb=laOnConditionThat(muil,mc,laPropExpression(&UP->PP,"enable_color_management"));{
             laUiItem* bb=laOnConditionThat(muil,mc,laPropExpression(&UP->PP,"enable_color_management"));{
-                laUiItem*bbr=laBeginRow(muil,mc,0,0);
-                laShowLabel(muil, mc, "Per screen config:", 0, 0)->Expand=1;
-                laShowItem(muil,mc,0,"LA_refresh_screens")->Flags|=LA_UI_FLAGS_ICON;
+#ifndef LAGUI_ANDROID
+                laShowSeparator(muil,mc)->Flags|=LA_UI_FLAGS_NO_DECAL;
+                laShowSeparator(muil,mcl);
+                laShowSeparator(muil,mc)->Flags|=LA_UI_FLAGS_NO_DECAL;
+                laShowLabel(muil, mcl, "Per screen config", 0, 0)->Flags|=LA_TEXT_ALIGN_RIGHT;
+                laUiItem*bbr=laBeginRow(muil,mcr,0,0);
                 laShowItemFull(muil, mcr, &UP->PP, "auto_switch_color_space",0,"text=Auto Switch",0,0);
                 laShowItemFull(muil, mcr, &UP->PP, "auto_switch_color_space",0,"text=Auto Switch",0,0);
+                laShowItem(muil,mcr,0,"LA_refresh_screens")->Flags|=LA_UI_FLAGS_ICON;
                 laEndRow(muil,bbr);
                 laEndRow(muil,bbr);
-                laShowItemFull(muil, mc, &UP->PP, "screens",0,0,laui_Screen,0);
-            }laEndCondition(muil,bb);
+                laShowItemFull(muil, mcr, &UP->PP, "screens",0,0,laui_Screen,0);
 #endif
 #endif
 
 
+                laShowSeparator(muil,mc)->Flags|=LA_UI_FLAGS_NO_DECAL;
+                laShowSeparator(muil,mcl);
+                laShowSeparator(muil,mc)->Flags|=LA_UI_FLAGS_NO_DECAL;
+                laShowLabel(muil, mcl, "Soft Proofing", 0, 0)->Flags|=LA_TEXT_ALIGN_RIGHT;
+                laUiItem*bs=laBeginRow(muil,mcr,0,0);
+                laShowItem(muil,mcr,0,"LA_new_proofing_profile");
+                laEndRow(muil,bs);
+                laUiItem* noproof=laOnConditionThat(muil,mc,laNot(laPropExpression(0,"la.user_preferences.proofing_profiles")));{
+                    laShowLabel(muil,mcr,"No icc profiles for soft proofing has been loaded.",0,0)->Flags|=LA_TEXT_LINE_WRAP;
+                }laElse(muil,noproof);{
+                    laShowItemFull(muil, mcr, &UP->PP, "proofing_profiles",0,0,laui_ProofingProfile,0);
+                }laEndCondition(muil,noproof);
+            }laEndCondition(muil,bb);
+
             laShowSeparator(muil, mc);
             laShowSeparator(muil, mc);
 
 
             if(MAIN.InitArgs.HasWorldObjects){
             if(MAIN.InitArgs.HasWorldObjects){

+ 1 - 1
resources/la_translations_es-ES.c

@@ -199,7 +199,7 @@ static const char *entries[]={
 "Thumbnail","Miniatura",
 "Thumbnail","Miniatura",
 "Backups","Respaldos",
 "Backups","Respaldos",
 "Auto Switch","Auto Conmutar",
 "Auto Switch","Auto Conmutar",
-"Per screen config:","Configuración por Monitor:",
+"Per screen config","Configuración por Monitor",
 "Will remove input mapping","Quitará mapeo de entrada",
 "Will remove input mapping","Quitará mapeo de entrada",
 "Will remove this key map entry","Quitará este mapeo de tecla de entrada",
 "Will remove this key map entry","Quitará este mapeo de tecla de entrada",
 "Select Signal","Seleccione Señal",
 "Select Signal","Seleccione Señal",

+ 1 - 1
resources/la_translations_zh-hans.c

@@ -194,7 +194,7 @@ static const char *entries[]={
 "Thumbnail","缩略图",
 "Thumbnail","缩略图",
 "Backups","备份文件",
 "Backups","备份文件",
 "Auto Switch","自动切换",
 "Auto Switch","自动切换",
-"Per screen config:","针对每个屏幕设置",
+"Per screen config","针对每个屏幕设置",
 "Will remove input mapping","将删除映射",
 "Will remove input mapping","将删除映射",
 "Will remove this key map entry","将删除该映射条目",
 "Will remove this key map entry","将删除该映射条目",
 "Select Signal","选择信号",
 "Select Signal","选择信号",

+ 6 - 3
resources/la_widgets.c

@@ -1457,9 +1457,12 @@ void la_ConditionToggleDraw(laUiItem *ui, int h){
             ui->Type->OperatorType->ParseArgs(0, ui->Instructions, &IconID, buf);
             ui->Type->OperatorType->ParseArgs(0, ui->Instructions, &IconID, buf);
         }
         }
     }
     }
-    if (buf[0]){ sprintf(buf2,"%s%s",transLate(buf),(NoDecal&&(ui->State==LA_UI_NORMAL))?" [...]":""); }
-    if (buf2[0]) tnsDrawStringAuto(buf2, la_UiTextColorState(bt,ui,UseState), ui->L+LA_M-sw, ui->R-LA_M-sw, ui->U-sw, ui->Flags|sf);
-    else tnsDrawStringAuto(ui->State == LA_UI_ACTIVE ? "⯆" : "⯈", la_UiTextColorState(bt,ui,UseState), ui->L+LA_M-sw, ui->R-LA_M-sw, ui->U-sw, ui->Flags|sf);
+    if(IconID){ tnsDrawIcon(IconID,la_UiTextColorState(bt,ui,UseState),ui->L,ui->R,ui->U,ui->Flags|sf); }
+    else{
+        if (buf[0]){ sprintf(buf2,"%s%s",transLate(buf),(NoDecal&&(ui->State==LA_UI_NORMAL))?" [...]":""); }
+        if (buf2[0]) tnsDrawStringAuto(buf2, la_UiTextColorState(bt,ui,UseState), ui->L+LA_M-sw, ui->R-LA_M-sw, ui->U-sw, ui->Flags|sf);
+        else tnsDrawStringAuto(ui->State == LA_UI_ACTIVE ? "⯆" : "⯈", la_UiTextColorState(bt,ui,UseState), ui->L+LA_M-sw, ui->R-LA_M-sw, ui->U-sw, ui->Flags|sf);
+    }
 }
 }
 void la_DrawColumnAdjusterRecursive(int U, int B, laColumn *c, int W, tnsVector4d color, int LeftMost){
 void la_DrawColumnAdjusterRecursive(int U, int B, laColumn *c, int W, tnsVector4d color, int LeftMost){
     if (c->LS){
     if (c->LS){