Lulucat

બે ઇરેઝર, અને ભૂંસવાનું કામ સ્ટ્રોકનું જ કેમ છે

Gaoge ZhangGaoge Zhang

અલગ એલિમેન્ટ તરીકે ઇરેઝર-સ્ટ્રોક રાખવો સ્વાભાવિક ડિઝાઇન લાગે છે. ઑબ્જેક્ટ ખસેડવાથી તે તૂટી જાય છે, તેથી Lulucat Notesમાં ભૂંસવાનું કામ જે સ્ટ્રોકની શાહી કાઢે છે તેનું જ છે.

અપડેટ કરેલું

નોટબુકમાં કંઈક ભૂંસતી વખતે લોકો બે અલગ બાબતોમાંથી એકનો અર્થ લે છે. ક્યારેક કોઈ નિશાન ખોટું હોય અને આખું નિશાન જતું રહેવું જોઈએ: માર્ગદર્શક રેખા, કાપી નાખેલો શબ્દ, આરામ કરતી હથેળીથી પડેલો ભટકેલો સ્ટ્રોક. ક્યારેક નિશાનનો માત્ર એક ભાગ ખોટો હોય છે: કોઈ અક્ષરનો અડધો ભાગ, આકૃતિની એક શાખા, અથવા વાક્યની આગળ નીકળી ગયેલા હાઇલાઇટર સ્વીપની પૂંછડી. Lulucat Notes હવે બંનેને બે અલગ સાધનો તરીકે આપે છે.

વધુ મુશ્કેલ ડિઝાઇનનો સવાલ એ છે કે ભૂંસવાનું કામ ક્યાં રહે છે.

સ્ટ્રોક ઇરેઝર સૌપ્રથમ આવ્યું

પહેલું ઇરેઝર આખા સ્ટ્રોક્સ ભૂંસી નાખતું હતું. એક ટચ દરેક સ્ટ્રોકને ચકાસે છે: bounding boxes લગભગ બધાને નકારી કાઢે છે, અને બચેલા સ્ટ્રોક્સ માટે eraser radius તથા એ segment સાથે interpolated stroke radiusના સરવાળા સામે point-to-segment squared distance test કરવામાં આવે છે. પહોળાઈ pressure સાથે બદલાય છે, તેથી એક nominal width એવી પાતળી strokesને ભૂંસી નાખશે જેને વપરાશકર્તાએ અડ્યો જ નથી અને એવી જાડી strokesને ચૂકી જશે જેને અડવામાં આવી હતી.

એક gesture એક undo entryમાં ભળી જાય છે, અને entry દરેક દૂર કરેલા સ્ટ્રોકને તેના original index સાથે સંગ્રહે છે. Undo તેમને reverse orderમાં પાછા મૂકે છે, જેથી stacking order બરાબર પહેલાં જેવો પાછો આવે છે.

આ ઇરેઝર ઝડપી, અનુમાનપાત્ર અને અડધો શબ્દ ભૂંસી નાખવામાં અસમર્થ છે.

MaLiang ઇરેઝરને બ્રશમાં ફેરવે છે

MaLiang, MIT લાઇસન્સ ધરાવતું drawing framework, જેમાંથી અમે હાઇલાઇટરનું stamp model પહેલાં ઉધાર લીધું હતું, partial erasingનો જવાબ ચોવીસ લાઇનોમાં આપે છે. તેનું Eraser એક Brush subclass છે, જે માત્ર એક વસ્તુ, blend options, override કરે છે અને add કરવાને બદલે subtract કરે છે. ઇરેઝર સ્ટ્રોક બીજા દરેક સ્ટ્રોકની જેમ એ જ listમાં એક element છે. Undo એ elementને દૂર કરે છે. કોઈ existing સ્ટ્રોકમાં ફેરફાર થતો નથી, કારણ કે ભૂંસણ માત્ર replay દરમિયાન, list orderમાં થાય છે.

અમે એ model ship કર્યું, અને બે device sessionsમાં તે તૂટી ગયું.

ઑબ્જેક્ટ ખસેડવાથી ગુમ થયેલો માલિક દેખાય છે

પહેલો અહેવાલ: lasso વડે સ્ટ્રોક્સ select કરો, તેમને drag કરો, અને hole પાછળ રહી જાય છે.

સ્ટ્રોક્સને ખસેડતા પહેલાં અને પછી ઇરેઝરના બે મોડેલની તુલના કરતા ચાર પેનલ. ઇરેઝર પોતાનું અલગ element હોય ત્યારે ખાલી જગ્યા જૂની જગ્યાએ રહે છે; ભૂંસવાનું કામ સ્ટ્રોકની માલિકીમાં હોય ત્યારે ખાલી જગ્યા શાહી સાથે ખસે છે.

એ જ ભૂંસાયેલા સ્ટ્રોક્સને જમણી તરફ ખસેડવામાં આવ્યા છે. ઉપર: ઇરેઝર પોતાનું અલગ element છે. નીચે: ભૂંસવાનું કામ સ્ટ્રોક્સની માલિકીનું છે.

Selectionથી સ્થિતિ વધુ ખરાબ થઈ. પસંદ કરાયેલા સ્ટ્રોક્સ bitmapમાંથી overlayમાં બહાર આવે છે અને ત્યાં ઇરેઝર element વિના સીધા draw થાય છે, તેથી ભૂંસાયેલો સ્ટ્રોક select કરતાની સાથે જ તે ફરી આખો દેખાવા લાગે છે.

બીજો અહેવાલ: ઇરેઝર હાઇલાઇટરની ઉપર તરતો હતો. અમારો renderer બે passesમાં replay કરે છે, પહેલાં હાઇલાઇટર્સ અને પછી પેન્સ, કારણ કે હાઇલાઇટરની શાહીએ અન્ય inkની નીચે રહેવું જોઈએ. ઇરેઝર elementએ બંને passesમાં ભાગ લેવો પડે છે, નહીં તો તે બંને પ્રકારના સ્ટ્રોક્સને erase કરી શકતો નથી. Pen passમાં ભાગ લેવાનો અર્થ દરેક હાઇલાઇટર draw થયા પછી ચલાવવાનો થાય છે, તેથી ઇરેઝર સમયક્રમમાં પછીથી દોરાયેલી હાઇલાઇટર સ્ટ્રોક્સને પણ કાપી નાખતો હતો.

બંને નિષ્ફળતાઓનું મૂળ એક જ છે. MaLiangમાં lasso, move અથવા brushes વચ્ચે layer order નથી, તેથી owner વિનાનું element ત્યાં પૂરતું છે. અમારા canvasમાં આ ત્રણેય છે, અને owner વિનાના ભૂંસણ માટે “શાહી ખસે ત્યારે શું થાય છે” અથવા “આ કયા layer પર કામ કરે છે” એ સવાલોના કોઈ નિર્ધારિત જવાબ નથી.

ભૂંસવાનું કામ સ્ટ્રોકની માલિકીનું છે

હવે દરેક Stroke પોતાના erase paths ધરાવે છે. ઇરેઝર કયા સ્ટ્રોક્સને અડે છે તે ચકાસે છે અને દરેકમાં canvas coordinatesમાં એક path ઉમેરે છે. એક સ્ટ્રોક રેન્ડર કરતી વખતે તેની શાહી અને તેનું પોતાનું ભૂંસણ transparency layerની અંદર દોરવામાં આવે છે:

context.beginTransparencyLayer(auxiliaryInfo: nil)
drawInk(stroke, in: context, clip: clip, colorOverride: colorOverride)
context.setBlendMode(.destinationOut)
for path in stroke.erasePaths { fillErasePath(path, in: context) }
context.endTransparencyLayer()

Destination-out destinationને જાળવી રાખે છે અને source alphaના પ્રમાણમાં તેને દૂર કરે છે:

Transparency layerની અંદર destination એ એક જ સ્ટ્રોક છે, તેથી operation paper, નીચેના સ્ટ્રોક્સ અથવા પછીથી દોરાયેલા સ્ટ્રોક્સ સુધી પહોંચી શકતું નથી. ભૂંસણ વિનાના સ્ટ્રોક્સ માટે layerનો કોઈ ખર્ચ નથી, અને એવા સ્ટ્રોક્સ લગભગ બધા જ છે: તેઓ original path વાપરે છે.

Ownership બંને નિષ્ફળતાઓનો સીધો જવાબ આપે છે. Translation erase pathsને sample points સાથે ખસેડે છે, તેથી ખસેડાયેલો સ્ટ્રોક પોતાની ખાલી જગ્યાઓ સાથે લઈ જાય છે. Selection overlay એ જ Stroke object draw કરે છે, તેથી selected સ્ટ્રોકમાં એ જ ખાલી જગ્યાઓ દેખાય છે. Layer orderનું મહત્વ રહેતું નથી, કારણ કે ભૂંસણ પોતાના સ્ટ્રોક સિવાય બીજી કોઈ વસ્તુ પર લાગુ પડતું નથી.

Undo gesture પર કામ કરે છે: એક entryમાં એ gestureથી બનેલી દરેક (stroke, path) જોડીની યાદી હોય છે, undo એ paths દૂર કરે છે અને redo તેમને ફરી append કરે છે. ભૂંસણની નીચેની શાહી ક્યારેય edit થતી નથી, તેથી કંઈ પણ reconstruct કરવું પડતું નથી.

ટાઇલ બિટમૅપ મારફતે જીવંત પ્રતિસાદ આવે છે

જે સ્ટ્રોક દોરાઈ રહ્યો હોય તેને સામાન્ય રીતે composited pageની ઉપર overlay તરીકે render કરવામાં આવે છે. ત્યાં ભૂંસણ કામ કરી શકતું નથી, કારણ કે એ overlay paper તેમજ ink બંનેની ઉપર બેઠું છે, અને destination-out paperમાં પણ કાણું પાડી દેશે.

તેથી ઇરેઝર તરત જ સ્ટ્રોક્સમાં લખે છે, અને નવા samplesના દરેક batchથી માત્ર affected rectangleનો local replay થાય છે. Tile pipeline પહેલેથી જ rectangle સાફ કરીને તેમાં intersect કરતા સ્ટ્રોક્સને replay કરે છે; ઇરેઝર એ જ માર્ગ ફરી વાપરે છે અને drawingની બીજી કોઈ semantic ઉમેરતું નથી.

બંને ઇરેઝર બાજુબાજુ

Toolbarમાં છુપાયેલા modeવાળા એક buttonને બદલે બે ઇરેઝર buttons છે. Partial eraser સ્ટ્રોકનો એક ભાગ કાઢે છે. Stroke eraser સંપર્ક થતાં આખા સ્ટ્રોક્સ દૂર કરે છે. તેમની ત્રિજ્યાઓ અલગ constants છે અને અત્યારે બંનેનું મૂલ્ય ચાર points છે.

આખો સ્ટ્રોક delete કરવાથી તેના erase paths પણ તેની સાથે જતાં રહે છે, કારણ કે તેઓ એ સ્ટ્રોકનો ભાગ છે, અને undo બંનેને સાથે પાછાં લાવે છે. Erase paths saved fileનો પણ ભાગ છે, અને બાકીની દરેક વસ્તુની જેમ quantize થાય છે: radius અને coordinates pointના tenthsમાં.

એક મર્યાદા હજુ બાકી છે. સંપૂર્ણપણે ભૂંસાયેલો સ્ટ્રોક data તરીકે હજી પણ અસ્તિત્વમાં રહે છે. તે કશું render કરતો નથી, પરંતુ lasso તેને હજી પણ select કરી શકે છે અને stroke eraser તેને હજી પણ delete કરી શકે છે; તે documentમાં જગ્યા પણ રોકે છે. સંપૂર્ણપણે ભૂંસાયેલા સ્ટ્રોક્સને collect કરવા માટે coverage testની જરૂર છે, જે અમે હજી લખ્યું નથી, તેથી અત્યારે તેઓ એમ જ રહે છે.

જ્યારે બીજા projectનું કોઈ model તમારા projectમાં કામ કરવાનું બંધ કરે, ત્યારે તફાવત સામાન્ય રીતે તમે copy કરેલા codeમાં હોતો નથી. તે એવા featuresમાં હોય છે જે એ projectમાં છે જ નહીં.