chromium/third_party/blink/renderer/core/layout/layout_font_accessor_win.cc

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/core/layout/layout_font_accessor_win.h"

#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/layout/inline/fragment_item.h"
#include "third_party/blink/renderer/core/layout/inline/inline_cursor.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/physical_box_fragment.h"
#include "third_party/blink/renderer/core/layout/physical_fragment_link.h"
#include "third_party/blink/renderer/platform/fonts/font_platform_data.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
#include "third_party/blink/renderer/platform/heap/collection_support/clear_collection_scope.h"

namespace blink {

namespace {

void GetFontsUsedByLayoutObject(const LayoutObject& layout_object,
                                FontFamilyNames& result);

void GetFontsUsedByFragment(const PhysicalBoxFragment& fragment,
                            FontFamilyNames& result) {
  for (InlineCursor cursor(fragment); cursor; cursor.MoveToNext()) {
    const FragmentItem& item = *cursor.Current().Item();
    if (item.IsText()) {
      if (const ShapeResultView* shape_result_view = item.TextShapeResult()) {
        HeapHashSet<Member<const SimpleFontData>> used_fonts =
            shape_result_view->UsedFonts();
        for (const auto& used_font : used_fonts) {
          result.font_names.insert(used_font->PlatformData().FontFamilyName());
        }
      }
      continue;
    }

    // If this is a nested BFC (e.g., inline block, floats), compute its area.
    if (item.Type() == FragmentItem::kBox) {
      if (const auto* layout_box = DynamicTo<LayoutBox>(item.GetLayoutObject()))
        GetFontsUsedByLayoutObject(*layout_box, result);
    }
  }

  // Traverse out-of-flow children. They are not in |FragmentItems|.
  for (const PhysicalFragmentLink& child : fragment.Children()) {
    if (const auto* child_layout_box =
            DynamicTo<LayoutBox>(child->GetLayoutObject()))
      GetFontsUsedByLayoutObject(*child_layout_box, result);
  }
}

void GetFontsUsedByLayoutObject(const LayoutObject& layout_object,
                                FontFamilyNames& result) {
  const LayoutObject* target = &layout_object;
  while (target) {
    // Use |InlineCursor| to traverse if |target| is an IFC.
    if (const auto* block_flow = DynamicTo<LayoutBlockFlow>(target)) {
      if (block_flow->HasFragmentItems()) {
        for (const PhysicalBoxFragment& fragment :
             block_flow->PhysicalFragments()) {
          GetFontsUsedByFragment(fragment, result);
        }
        target = target->NextInPreOrderAfterChildren(&layout_object);
        continue;
      }
    }
    target = target->NextInPreOrder(&layout_object);
  }
}

}  // namespace

void GetFontsUsedByFrame(const LocalFrame& frame, FontFamilyNames& result) {
  GetFontsUsedByLayoutObject(frame.ContentLayoutObject()->RootBox(), result);
}

}  // namespace blink