RenderingNG عمیق شیرجه: تکه تکه شدن بلوک LayoutNG

تکه تکه شدن بلاک در LayoutNG اکنون کامل شده است. در این مقاله بیاموزید که چگونه کار می کند و چرا مهم است.

مورتن استنشورن
Morten Stenshorne

من مورتن استنشورن هستم، یک مهندس طرح‌بندی در تیم رندر Blink در Google. من از اوایل دهه 2000 در توسعه موتور مرورگر شرکت داشتم، و بسیار لذت بردم، مانند کمک به انجام تست اسید2 در موتور Presto (Opera 12 و قبل از آن)، و مهندسی معکوس سایر مرورگرها برای چیدمان جدول را در Presto اصلاح کنید. من همچنین بیشتر از آن سال‌هایی را که می‌خواهم اعتراف کنم، صرف تقسیم‌بندی بلوک‌ها، و به‌ویژه، multicol در Presto، WebKit، و Blink کرده‌ام. در طول چند سال گذشته در گوگل، من عمدتاً بر روی رهبری کار افزودن پشتیبانی از تکه تکه شدن بلوک به LayoutNG تمرکز کرده ام. به من در این بررسی عمیق در پیاده سازی قطعه قطعه شدن بلوک بپیوندید، زیرا ممکن است این آخرین باری باشد که من تکه تکه شدن بلوک را اجرا می کنم. :)

تکه تکه شدن بلوک چیست؟

تکه تکه شدن بلوک در مورد تقسیم یک جعبه در سطح بلوک CSS (مانند یک بخش یا پاراگراف) به چند قطعه است، زمانی که به عنوان یک کل در یک محفظه قطعه به نام Fragmentainer قرار نمی گیرد. Fragmentainer یک عنصر نیست، بلکه نشان دهنده یک ستون در طرح چند ستونی، یا یک صفحه در رسانه صفحه شده است. برای اینکه تکه تکه شدن اتفاق بیفتد، محتوا باید در یک زمینه تقسیم بندی باشد. یک زمینه تکه تکه شدن معمولاً توسط یک ظرف چند ستونی ایجاد می شود (محتوا به ستون ها تقسیم می شود) یا هنگام چاپ (محتوا به صفحات تقسیم می شود). ممکن است لازم باشد یک پاراگراف طولانی با خطوط زیاد به چند قطعه تقسیم شود، به طوری که اولین خطوط در قطعه اول و خطوط باقی مانده در قطعات بعدی قرار گیرند.

یک پاراگراف از متن به دو ستون تقسیم شده است.
در این مثال یک پاراگراف با استفاده از طرح چند ستونی به دو ستون تقسیم شده است. هر ستون یک قطعه ساز است که نشان دهنده یک قطعه از جریان تکه تکه شده است.

تکه تکه شدن بلوک مشابه نوع شناخته شده دیگری از تکه تکه شدن است: تکه تکه شدن خط (که در غیر این صورت به عنوان "شکستن خط" شناخته می شود). هر عنصر درون خطی که از بیش از یک کلمه تشکیل شده باشد (هر گره متن، هر عنصر <a> و غیره) و اجازه شکست خط را بدهد، ممکن است به چند قطعه تقسیم شود. هر قطعه در یک جعبه خط متفاوت قرار می گیرد. یک کادر خطی، تکه تکه شدن درون خطی است که معادل یک قطعه ساز برای ستون ها و صفحات است.

تکه تکه شدن بلوک LayoutNG چیست؟

LayoutNGBlockFragmentation بازنویسی موتور تکه تکه سازی برای LayoutNG است و پس از سال ها کار، سرانجام اولین قطعات در اوایل سال جاری در کروم 102 ارسال شد. این مشکلات طولانی مدت را که اساساً در موتور "میراث" ما قابل رفع نبود، برطرف کرد. از نظر ساختارهای داده، چندین ساختار داده قبل از NG را با قطعات NG که مستقیماً در درخت قطعه نشان داده شده اند جایگزین می کند.

به عنوان مثال، ما اکنون از مقدار 'avoid' برای ویژگی های 'break-before' و 'break-after' CSS پشتیبانی می کنیم، که به نویسندگان اجازه می دهد تا از شکسته شدن درست بعد از هدر اجتناب کنند. اگر آخرین چیزی که در صفحه قرار می گیرد یک هدر باشد، در حالی که محتوای بخش از صفحه بعد شروع می شود، به طور کلی خوب به نظر نمی رسد. در عوض بهتر است قبل از ضربه سر شکسته شود. برای نمونه به شکل زیر مراجعه کنید.

مثال اول یک عنوان را در پایین صفحه نشان می دهد، دومی آن را در بالای صفحه بعد با محتوای مرتبط نشان می دهد.

Chrome 102 همچنین از سرریز تکه تکه شدن پشتیبانی می کند، به طوری که محتوای یکپارچه (قرار می رود غیرقابل شکست باشد) به چندین ستون تقسیم نشود و جلوه های رنگ مانند سایه ها و تبدیل ها به درستی اعمال شوند.

تکه تکه شدن بلاک در LayoutNG اکنون کامل شده است

در زمان نوشتن این مطلب، ما پشتیبانی کامل از تکه تکه شدن بلوک را در LayoutNG تکمیل کرده ایم. تکه تکه شدن هسته (کانتینرهای بلوکی، از جمله طرح‌بندی خط، شناورها و موقعیت‌یابی خارج از جریان) در Chrome 102 ارسال شد. تکه‌تکه‌شدن انعطاف‌پذیر و شبکه‌ای در Chrome 103 و تقسیم‌بندی جدول در Chrome 106 ارسال شد. در نهایت، چاپ در Chrome 108 ارسال شد. تکه تکه شدن بلوک آخرین ویژگی بود که برای اجرای طرح بندی به موتور قدیمی بستگی داشت. این بدان معناست که از Chrome 108، موتور قدیمی دیگر برای اجرای طرح‌بندی استفاده نخواهد شد.

علاوه بر چیدمان واقعی محتوا، ساختارهای داده LayoutNG از نقاشی و تست ضربه پشتیبانی می‌کنند، اما ما همچنان به برخی از ساختارهای داده قدیمی برای APIهای جاوا اسکریپت تکیه می‌کنیم که اطلاعات طرح‌بندی را می‌خوانند، مانند offsetLeft و offsetTop .

چیدمان همه چیز با NG، پیاده سازی و ارسال ویژگی های جدیدی را که فقط دارای پیاده سازی LayoutNG هستند (و بدون مشابه موتور قدیمی)، مانند جستارهای کانتینر CSS ، موقعیت یابی لنگر، MathML و طرح بندی سفارشی (Houdini) ممکن می کند. برای سؤالات کانتینر، آن را کمی از قبل ارسال کردیم، با هشداری به توسعه دهندگان مبنی بر اینکه چاپ هنوز پشتیبانی نمی شود.

ما اولین قسمت LayoutNG را در سال 2019 ارسال کردیم که شامل چیدمان کانتینر بلوک معمولی، چیدمان درون خطی، شناورها و موقعیت‌یابی خارج از جریان بود، اما هیچ پشتیبانی برای انعطاف‌پذیری، شبکه، یا جداول و اصلاً پشتیبانی از تکه تکه شدن بلوک وجود نداشت. ما به استفاده از موتور طرح‌بندی قدیمی برای انعطاف‌پذیری، شبکه، جداول، به علاوه هر چیزی که شامل تکه تکه شدن بلوک باشد، بازمی‌گردیم. این حتی برای عناصر بلوک، درون خطی، شناور و خارج از جریان درون محتوای تکه تکه شده نیز صادق بود - همانطور که می بینید، ارتقاء چنین موتور طرح بندی پیچیده ای در محل کار بسیار ظریفی است.

علاوه بر این، باور کنید یا نه، تا اواسط سال 2019 اکثر عملکردهای اصلی طرح‌بندی قطعه‌بندی بلوک LayoutNG قبلاً (پشت پرچم) پیاده‌سازی شده بود. بنابراین، چرا ارسال آن اینقدر طول کشید؟ پاسخ کوتاه این است: تکه تکه شدن باید به درستی با بخش‌های قدیمی مختلف سیستم همزیستی داشته باشد، که تا زمانی که همه وابستگی‌ها ارتقا پیدا نکنند، نمی‌توان آنها را حذف یا ارتقا داد. برای پاسخ طولانی، جزئیات زیر را ببینید.

تعامل موتور قدیمی

ساختارهای داده قدیمی هنوز مسئول APIهای جاوا اسکریپت هستند که اطلاعات طرح‌بندی را می‌خوانند، بنابراین باید داده‌ها را به‌گونه‌ای که موتور قدیمی آن را بفهمد، بازنویسی کنیم. این شامل به‌روزرسانی صحیح ساختارهای داده چند ستونی قدیمی، مانند LayoutMultiColumnFlowThread است.

شناسایی و مدیریت موتور قدیمی

هنگامی که محتوایی در داخل وجود داشت که هنوز با تکه تکه شدن بلوک LayoutNG قابل مدیریت نبود، مجبور شدیم به موتور طرح‌بندی قدیمی بازگردیم. در زمان ارسال قطعه بندی بلوک LayoutNG هسته (بهار 2022)، که شامل فلکس، شبکه، جداول و هر چیزی که چاپ شده بود. این امر به ویژه دشوار بود زیرا ما نیاز داشتیم قبل از ایجاد اشیاء در درخت طرح، نیاز به بازگشت قدیمی را تشخیص دهیم. به عنوان مثال، قبل از اینکه بدانیم آیا یک اجداد ظرف چند ستونی وجود دارد یا نه، و قبل از اینکه بدانیم کدام گره‌های DOM تبدیل به یک زمینه قالب‌بندی می‌شوند یا خیر، باید تشخیص می‌دادیم. این یک مشکل مرغ و تخم مرغ است که راه حل کاملی ندارد، اما تا زمانی که تنها رفتار نادرست آن موارد مثبت کاذب باشد (بازگشت به میراث زمانی که واقعاً نیازی نیست)، اشکالی ندارد، زیرا هر گونه اشکال در آن رفتار چیدمان یکی است. Chromium قبلاً دارد، موارد جدیدی نیست.

پیاده روی درخت از قبل رنگ آمیزی کنید

پیش رنگ کاری است که ما بعد از چیدمان، اما قبل از رنگ آمیزی انجام می دهیم . چالش اصلی این است که ما هنوز باید روی درخت شی layout قدم بزنیم، اما اکنون قطعات NG داریم—پس چگونه با آن کنار بیاییم؟ ما هر دو شی layout و درختان قطعه NG را همزمان راه می رویم! این بسیار پیچیده است، زیرا نقشه برداری بین دو درخت بی اهمیت نیست. در حالی که ساختار درخت شی layout شباهت زیادی به درخت DOM دارد، درخت قطعه یک خروجی از چیدمان است، نه ورودی آن. جدا از اینکه واقعاً تأثیر هر قطعه‌سازی را منعکس می‌کند، از جمله تکه تکه‌شدن درون خطی (قطعات خط) و قطعه‌سازی بلوک (قطعات ستون یا صفحه)، درخت قطعه همچنین یک رابطه مستقیم والد-فرزند بین یک بلوک حاوی و نوادگان DOM که آن قطعه را دارند، دارد. بلوک حاوی آنها به عنوان مثال، در درخت قطعه، یک قطعه تولید شده توسط یک عنصر کاملاً موقعیت‌یافته، فرزند مستقیم قطعه بلوک حاوی آن است، حتی اگر گره‌های دیگری در زنجیره اجدادی بین نسل خارج از جریان و بلوک حاوی آن وجود داشته باشد.

زمانی که یک عنصر خارج از جریان در داخل تکه تکه‌شدن قرار می‌گیرد، پیچیده‌تر می‌شود، زیرا در این صورت قطعات خارج از جریان، فرزندان مستقیم Fragmentainer می‌شوند (و نه فرزند چیزی که CSS فکر می‌کند بلوک حاوی است). متأسفانه این مشکلی بود که باید حل می شد تا بتوان بدون دردسر زیاد با موتور قدیمی همزیستی کرد. در آینده، ما باید بتوانیم بسیاری از این کدها را ساده کنیم، زیرا LayoutNG به گونه ای طراحی شده است که به طور انعطاف پذیر از تمام حالت های طرح بندی مدرن پشتیبانی کند.

مشکلات موتور قطعه قطعه سازی قدیمی

موتور قدیمی، طراحی شده در دوره قبلی وب، واقعاً مفهومی از تکه تکه شدن ندارد، حتی اگر قطعه قطعه شدن از نظر فنی در آن زمان نیز وجود داشته باشد (به منظور پشتیبانی از چاپ). پشتیبانی از تکه تکه شدن فقط چیزی بود که در بالا پیچ می شد (چاپ) یا مقاوم سازی می شد (چند ستون).

هنگام چیدمان محتوای تکه تکه‌پذیر، موتور قدیمی همه چیز را در یک نوار بلند قرار می‌دهد که عرض آن به اندازه یک ستون یا صفحه است و ارتفاع آن به اندازه‌ای است که برای گنجاندن محتوای آن لازم است. این نوار بلند به صفحه نمایش داده نمی شود - آن را به عنوان رندر به یک صفحه مجازی در نظر بگیرید که برای نمایش نهایی مجدداً مرتب می شود. از نظر مفهومی شبیه به چاپ کل مقاله روزنامه کاغذی در یک ستون، و سپس استفاده از قیچی برای برش آن به چند قسمت در مرحله دوم است. (در آن روزگار، برخی روزنامه ها در واقع از تکنیک هایی مشابه این استفاده می کردند!)

موتور قدیمی یک صفحه خیالی یا مرز ستون را در نوار ردیابی می کند. این به آن اجازه می دهد محتوایی را که از مرز خارج نمی شود به صفحه یا ستون بعدی هدایت کند. برای مثال، اگر فقط نیمه بالایی یک خط با آنچه که موتور فکر می‌کند صفحه فعلی است، قرار می‌گیرد، یک «بند صفحه‌بندی» را وارد می‌کند تا آن را به سمت پایین فشار دهد تا جایی که موتور فرض می‌کند بالای صفحه بعدی است. . سپس، بیشتر کارهای قطعه‌سازی واقعی ("برش با قیچی و قرار دادن") پس از طرح‌بندی در حین رنگ‌آمیزی و نقاشی، با برش دادن نوار بلند محتوا به صفحات یا ستون‌ها (با برش و ترجمه بخش‌ها) انجام می‌شود. این امر چند چیز را اساساً غیرممکن می‌کند، مانند اعمال تبدیل‌ها و موقعیت‌یابی نسبی پس از تکه تکه شدن (که این همان چیزی است که مشخصات نیاز دارد). بعلاوه، در حالی که در موتور قدیمی از تکه تکه شدن جدول پشتیبانی می شود، اصلاً پشتیبانی از تکه تکه شدن منعطف یا گرید وجود ندارد.

در اینجا تصویری از نحوه نمایش طرح‌بندی سه ستونی به صورت داخلی در موتور قدیمی، قبل از استفاده از قیچی، قرار دادن و چسب ارائه می‌شود (ما یک ارتفاع مشخص داریم، به طوری که فقط چهار خط جا می‌شود، اما مقداری فضای اضافی در پایین وجود دارد):

نمایش داخلی به عنوان یک ستون با ستون های صفحه بندی که در آن محتوا شکسته می شود، و نمایش روی صفحه به عنوان سه ستون.

از آنجایی که موتور طرح‌بندی قدیمی در واقع محتوا را در طول طرح‌بندی تکه تکه نمی‌کند، مصنوعات عجیب و غریب زیادی وجود دارد، مانند موقعیت‌یابی نسبی و تبدیل‌ها که به اشتباه اعمال می‌شوند، و سایه‌های جعبه در لبه‌های ستون بریده می‌شوند.

در اینجا یک مثال ساده با text-shadow آورده شده است:

موتور قدیمی به خوبی از عهده این کار بر نمی آید:

سایه های متن بریده شده در ستون دوم قرار می گیرند.

آیا می بینید که چگونه سایه متن از خط در ستون اول بریده می شود و در عوض در بالای ستون دوم قرار می گیرد؟ دلیلش این است که موتور طرح بندی قدیمی، تکه تکه شدن را درک نمی کند!

باید شبیه این باشد (و اینطوری است که با NG نشان می دهد):

دو ستون متن با سایه ها به درستی نمایش داده می شوند.

در مرحله بعد، اجازه دهید آن را کمی پیچیده تر کنیم، با تبدیل و سایه. توجه کنید که چگونه در موتور قدیمی، برش نادرست و خونریزی ستون وجود دارد. دلیلش این است که تبدیل‌ها براساس مشخصات قرار است به عنوان یک افکت پس از چیدمان و پس از تکه تکه‌سازی اعمال شوند. با تقسیم بندی LayoutNG هر دو به درستی کار می کنند. این باعث افزایش تعامل با فایرفاکس می شود، که برای مدتی از پشتیبانی خوب از تکه تکه شدن برخوردار بوده و اکثر تست ها در این زمینه نیز در آنجا گذرانده شده اند.

کادرها به اشتباه در دو ستون شکسته شده اند.

موتور قدیمی همچنین با محتوای یکپارچه بلند مشکل دارد. اگر محتوا برای تقسیم به چند بخش واجد شرایط نباشد، یکپارچه است. عناصر با اسکرول سرریز یکپارچه هستند، زیرا برای کاربران منطقی نیست که در یک منطقه غیر مستطیلی پیمایش کنند. جعبه های خط و تصاویر نمونه های دیگری از محتوای یکپارچه هستند. در اینجا یک مثال است:

اگر قطعه محتوای یکپارچه آنقدر بلند باشد که در یک ستون قرار نگیرد، موتور قدیمی آن را به طرز وحشیانه‌ای برش می‌دهد (که منجر به رفتار بسیار "جالب" در هنگام تلاش برای اسکرول ظرف قابل پیمایش می‌شود):

به جای اینکه اجازه دهید ستون اول سرریز شود (همانطور که با تکه تکه شدن بلوک LayoutNG انجام می شود):

ALT_TEXT_HERE

موتور قدیمی از شکست های اجباری پشتیبانی می کند. به عنوان مثال، <div style="break-before:page;"> یک صفحه شکست را قبل از DIV درج می کند. با این حال، فقط پشتیبانی محدودی برای یافتن شکست های غیراجباری بهینه دارد. break-inside:avoid و orphans and widows پشتیبانی می کند، اما برای جلوگیری از شکست بین بلوک ها، برای مثال، اگر از طریق break-before:avoid درخواست شود، هیچ پشتیبانی وجود ندارد. این مثال را در نظر بگیرید:

متن به دو ستون تقسیم شده است.

در اینجا، عنصر #multicol دارای فضایی برای 5 خط در هر ستون است (زیرا 100 پیکسل ارتفاع دارد و ارتفاع خط 20 پیکسل است)، بنابراین همه #firstchild می تواند در ستون اول قرار بگیرد. با این حال، خواهر و برادر #secondchild فرزندش break-before:avoid دارد، به این معنی که محتوا آرزو می‌کند بین آنها وقفه ایجاد نشود. از آنجایی که ارزش widows 2 است، باید 2 خط #firstchild را به ستون دوم فشار دهیم تا تمام درخواست‌های اجتناب از شکست را رعایت کنیم. Chromium اولین موتور مرورگری است که به طور کامل از این ترکیب از ویژگی ها پشتیبانی می کند.

چگونه تکه تکه شدن NG کار می کند

موتور طرح‌بندی NG معمولاً سند را با عبور از عمق درخت CSS نشان می‌دهد. هنگامی که تمام نوادگان یک گره چیده شدند، طرح بندی آن گره را می توان با تولید یک NGPhysicalFragment و بازگشت به الگوریتم چیدمان والد تکمیل کرد. این الگوریتم قطعه را به لیست قطعات فرزند خود اضافه می کند و پس از تکمیل شدن همه فرزندان، قطعه ای را با تمام قطعات فرزند خود در داخل آن ایجاد می کند. با این روش یک درخت قطعه برای کل سند ایجاد می کند. با این حال، این یک ساده‌سازی بیش از حد است: برای مثال، عناصری که در حالت خارج از جریان قرار دارند باید از جایی که در درخت DOM وجود دارند به بلوک حاوی خود حباب شوند تا بتوان آنها را چیدمان کرد. من این جزئیات پیشرفته را در اینجا به خاطر سادگی نادیده می‌گیرم.

همراه با خود جعبه CSS، LayoutNG یک فضای محدودیت برای الگوریتم طرح‌بندی فراهم می‌کند. این اطلاعاتی مانند فضای موجود برای طرح‌بندی، ایجاد زمینه قالب‌بندی جدید و کاهش حاشیه میانی نتایج محتوای قبلی را در اختیار الگوریتم قرار می‌دهد. فضای محدودیت همچنین اندازه بلوک چیدمان شده قطعه ساز را می داند و بلوک فعلی در آن جابجا می شود. این نشان می دهد که کجا باید شکسته شود.

هنگامی که تکه تکه شدن بلوک درگیر است، چیدمان فرزندان باید در یک وقفه متوقف شود. دلایل شکستن عبارتند از کمبود فضا در صفحه یا ستون، یا شکست اجباری. سپس قطعاتی را برای گره‌هایی که بازدید کرده‌ایم تولید می‌کنیم و تا آخر به ریشه زمینه قطعه‌سازی (محفظه چندکولی یا در صورت چاپ، ریشه سند) برمی‌گردیم. سپس، در ریشه زمینه قطعه قطعه شدن، برای یک قطعه ساز جدید آماده می شویم، و دوباره به درخت فرود می آییم، و از همان جایی که قبل از استراحت متوقف کرده بودیم، ادامه می دهیم.

ساختار داده مهم برای ارائه ابزارهای از سرگیری طرح بندی پس از یک استراحت NGBlockBreakToken نامیده می شود. این شامل تمام اطلاعات مورد نیاز برای از سرگیری طرح بندی به طور صحیح در Fragmentainer بعدی است. یک NGBlockBreakToken با یک گره مرتبط است، و یک درخت NGBlockBreakToken را تشکیل می دهد، به طوری که هر گره ای که نیاز به از سرگیری دارد، نشان داده می شود. یک NGBlockBreakToken به NGPhysicalBoxFragment که برای گره هایی که در داخل شکسته می شوند، متصل می شود. نشانه های شکست به والدین تکثیر می شوند و درختی از نشانه های شکست را تشکیل می دهند. اگر ما نیاز به شکستن قبل از یک گره (به جای داخل آن) داشته باشیم، هیچ قطعه ای تولید نمی شود، اما گره والد هنوز باید یک نشانه شکستن "break-before" برای گره ایجاد کند، تا بتوانیم زمانی که آن را چیدمان کنیم شروع کنیم. در قطعه گره بعدی به همان موقعیت در درخت گره می رسیم.

شکستن ها زمانی درج می شوند که ما یا فضای قطعه سازی را تمام می کنیم (یک شکست اجباری)، یا زمانی که یک شکست اجباری درخواست می شود.

قوانینی در مشخصات برای شکست های غیراجباری بهینه وجود دارد، و قرار دادن یک شکست دقیقاً در جایی که فضای خالی ما تمام می شود، همیشه کار درستی نیست. به عنوان مثال، ویژگی های مختلف CSS مانند break-before وجود دارد که بر انتخاب مکان شکست تأثیر می گذارد. بنابراین، در حین چیدمان، برای اجرای صحیح بخش مشخصات شکست های غیر اجباری ، باید نقاط شکست احتمالاً خوب را پیگیری کنیم. این رکورد به این معنی است که می‌توانیم به عقب برگردیم و از آخرین بهترین نقطه شکست ممکن استفاده کنیم، اگر در نقطه‌ای که درخواست‌های اجتناب از شکست را نقض می‌کنیم فضای خالیمان تمام شود (مثلاً break-before:avoid یا orphans:7 ). به هر نقطه انفصال ممکن امتیازی داده می شود که از "فقط این کار را به عنوان آخرین راه حل انجام دهید" تا "مکانی عالی برای شکستن" و مقادیری در بین آن ها را شامل می شود. اگر یک مکان استراحت به عنوان "عالی" امتیاز پیدا کند، به این معنی است که اگر ما آنجا را زیر پا بگذاریم، هیچ قانون نقضی نقض نمی شود (و اگر این امتیاز را دقیقاً در نقطه ای به دست آوریم که فضای خالی ما تمام شده است، دیگر نیازی نیست به دنبال چیز بهتری باشیم. ). اگر امتیاز «آخرین راه حل» باشد، نقطه شکست حتی یک امتیاز معتبر نیست، اما اگر چیزی بهتر از آن پیدا نکنیم، ممکن است برای جلوگیری از سرریز شدن بیشتر از آن، شکست بخوریم.

نقاط انفصال معتبر عموماً فقط بین خواهر و برادرها (جعبه‌های خط یا بلوک‌ها) اتفاق می‌افتد و نه، برای مثال، بین والدین و فرزند اولش ( نقاط انفصال کلاس C یک استثنا هستند، اما ما نیازی به بحث در مورد آن‌ها در اینجا نداریم). یک نقطه شکست معتبر برای مثال قبل از یک برادر بلوکی با break-before:avoid وجود دارد ، اما جایی بین "کامل" و "آخرین راه حل" است.

در طول طرح‌بندی، بهترین نقطه شکست را که تاکنون در ساختاری به نام NGEarlyBreak یافت شده است، پیگیری می‌کنیم. شکست زودهنگام یک نقطه شکست احتمالی قبل یا داخل یک گره بلوک یا قبل از یک خط (یک خط ظرف بلوک یا یک خط فلکس) است. ممکن است زنجیره یا مسیری از اشیاء NGEarlyBreak تشکیل دهیم، در صورتی که بهترین نقطه شکست جایی در اعماق چیزی باشد که در زمانی که فضا به پایان می‌رسد، زودتر از آن عبور کرده‌ایم. در اینجا یک مثال است:

در این مورد، درست قبل از #second فضای خالی ما تمام می‌شود، اما دارای «break-before:avoid» است که امتیاز موقعیت مکانی استراحت «تخطی از شکست اجتناب» را دریافت می‌کند. در آن نقطه ما یک زنجیره NGEarlyBreak از "inside #outer > inside #middle > inside #inner > قبل از "خط 3"، با "perfect" داریم، بنابراین ترجیح می دهیم آنجا را بشکنیم. بنابراین باید برگردیم و دوباره اجرا کنیم. layout از ابتدای #outer (و این بار NGEarlyBreak را که پیدا کردیم رد کنید)، تا بتوانیم قبل از "خط 3" در #inner بشکنیم (قبل از "خط 3" بشکنیم، به طوری که 4 خط باقیمانده به پایان برسد در قطعه ساز بعدی و به منظور احترام به widows:4 .)

الگوریتم طوری طراحی شده است که همیشه در بهترین نقطه شکست ممکن - همانطور که در مشخصات تعریف شده است - با انداختن قوانین به ترتیب صحیح شکسته شود، اگر نمی توان همه آنها را برآورده کرد. توجه داشته باشید که ما فقط باید حداکثر یک بار در هر جریان تکه تکه‌بندی مجدد طرح‌بندی کنیم. تا زمانی که در مرحله دوم طرح بندی هستیم، بهترین مکان شکست قبلاً به الگوریتم های چیدمان منتقل شده است، این مکان شکست است که در اولین پاس طرح کشف شد و به عنوان بخشی از خروجی طرح در آن دور ارائه شد. در مرحله دوم چیدمان، تا زمانی که فضای خالی مان تمام نشود، چیدمان نمی‌کنیم - در واقع انتظار نمی‌رود که فضا کم شود (این در واقع یک خطا است)، زیرا یک ماده فوق‌العاده شیرین برای ما ارائه شده است. (خوب، به همان اندازه که در دسترس بود) مکانی برای قرار دادن یک استراحت زودهنگام، برای جلوگیری از نقض غیر ضروری قوانین. بنابراین ما فقط تا آن نقطه دراز می کنیم و می شکنیم.

با توجه به این نکته، گاهی اوقات لازم است برخی از درخواست‌های اجتناب از وقفه را نقض کنیم، اگر این به جلوگیری از سرریز شدن قطعه قطعه کمک می‌کند. مثال:

در اینجا، درست قبل از #second فضای خالی ما تمام می‌شود، اما دارای "break-before:avoid" است. دقیقاً مانند نمونه آخر به «عدم نقض نقض» ترجمه شده است. ما همچنین یک NGEarlyBreak با "تخطی از یتیمان و بیوه ها" داریم (در داخل #first > قبل از "خط 2")، که هنوز هم کامل نیست، اما بهتر از "تخطی از شکستن اجتناب کنید". بنابراین ما قبل از "خط 2" شکسته می شویم و درخواست یتیمان / بیوه ها را نقض می کنیم. مشخصات در 4.4 به این موضوع می پردازد. Unforced Breaks ، که در آن تعریف می‌کند که اگر نقاط شکست کافی برای جلوگیری از سرریز قطعه قطعه‌ای نداشته باشیم، ابتدا کدام قوانین شکسته را نادیده می‌گیریم.

خلاصه

هدف عملکردی اصلی پروژه تقسیم‌بندی بلوک LayoutNG، ارائه اجرای پشتیبانی از معماری LayoutNG از هر چیزی بود که موتور قدیمی از آن پشتیبانی می‌کند، و تا آنجا که ممکن است، به غیر از رفع اشکال. استثنای اصلی در اینجا پشتیبانی بهتر اجتناب از شکست است (به عنوان مثال break-before:avoid )، زیرا این بخش اصلی موتور تکه تکه شدن است، بنابراین باید از ابتدا در آنجا وجود داشته باشد، زیرا اضافه کردن آن بعدا به معنای بازنویسی دیگری است. .

اکنون که تکه تکه‌سازی بلوک LayoutNG به پایان رسیده است، می‌توانیم کار بر روی افزودن قابلیت‌های جدید مانند پشتیبانی از اندازه‌های مختلف صفحه هنگام چاپ، کادرهای حاشیه @page هنگام چاپ، box-decoration-break:clone و غیره شروع کنیم. و مانند LayoutNG به طور کلی ، ما انتظار داریم که میزان باگ و بار تعمیر و نگهداری سیستم جدید در طول زمان به میزان قابل توجهی کمتر شود.

با تشکر برای خواندن!

سپاسگزاریها