Remove SkiaState Removes SkiaState by moving the remaining methods into CFX_SkiaDeviceDriver. Bug: pdfium:1963 Change-Id: Iba36aeb61ea1502f9eeb510f8cd341dc658fe485 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/104610 Commit-Queue: K. Moon <kmoon@chromium.org> Reviewed-by: Nigi <nigi@chromium.org>
diff --git a/core/fxge/BUILD.gn b/core/fxge/BUILD.gn index 8d41381..d05386f 100644 --- a/core/fxge/BUILD.gn +++ b/core/fxge/BUILD.gn
@@ -129,6 +129,8 @@ "../fxcrt", ] + public_deps = [] + if (is_component_build || use_system_freetype) { # ft_adobe_glyph_list is not exported from the Freetype shared library so we # need it defined in component builds and builds using system freetype. @@ -144,7 +146,7 @@ if (pdf_use_skia) { sources += [ "skia/fx_skia_device.cpp" ] - deps += [ "//skia" ] + public_deps += [ "//skia" ] } if (is_android) {
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp index dfd0cb9..9d0ebf9 100644 --- a/core/fxge/skia/fx_skia_device.cpp +++ b/core/fxge/skia/fx_skia_device.cpp
@@ -27,7 +27,6 @@ #include "core/fxcrt/data_vector.h" #include "core/fxcrt/fx_2d_size.h" #include "core/fxcrt/fx_coordinates.h" -#include "core/fxcrt/fx_memory_wrappers.h" #include "core/fxcrt/fx_system.h" #include "core/fxcrt/stl_util.h" #include "core/fxge/calculate_pitch.h" @@ -75,10 +74,6 @@ #include "third_party/skia/include/effects/SkGradientShader.h" #include "third_party/skia/include/pathops/SkPathOps.h" -// Assumes Skia is not going to add non-data members to its fundamental types. -FX_DATA_PARTITION_EXCEPTION(SkPoint); -FX_DATA_PARTITION_EXCEPTION(SkRSXform); - namespace { #define SHOW_SKIA_PATH 0 // set to 1 to print the path contents @@ -785,180 +780,39 @@ return bitmap; } -} // namespace - -// TODO(crbug.com/pdfium/1936): Inline remaining methods. -class SkiaState { - public: - // mark all cached state as uninitialized - explicit SkiaState(SkCanvas* pCanvas) : m_pCanvas(pCanvas) {} - - bool HasRSX(pdfium::span<const TextCharPos> char_pos, - float* scaleXPtr, - bool* oneAtATimePtr) const { - bool useRSXform = false; - bool oneAtATime = false; - float scaleX = 1; - for (const TextCharPos& cp : char_pos) { - if (!cp.m_bGlyphAdjust) - continue; - bool upright = 0 == cp.m_AdjustMatrix[1] && 0 == cp.m_AdjustMatrix[2]; - if (cp.m_AdjustMatrix[0] != cp.m_AdjustMatrix[3]) { - if (upright && 1 == cp.m_AdjustMatrix[3]) { - if (1 == scaleX) - scaleX = cp.m_AdjustMatrix[0]; - else if (scaleX != cp.m_AdjustMatrix[0]) - oneAtATime = true; - } else { +bool HasRSX(pdfium::span<const TextCharPos> char_pos, + float* scaleXPtr, + bool* oneAtATimePtr) { + bool useRSXform = false; + bool oneAtATime = false; + float scaleX = 1; + for (const TextCharPos& cp : char_pos) { + if (!cp.m_bGlyphAdjust) { + continue; + } + bool upright = 0 == cp.m_AdjustMatrix[1] && 0 == cp.m_AdjustMatrix[2]; + if (cp.m_AdjustMatrix[0] != cp.m_AdjustMatrix[3]) { + if (upright && 1 == cp.m_AdjustMatrix[3]) { + if (1 == scaleX) { + scaleX = cp.m_AdjustMatrix[0]; + } else if (scaleX != cp.m_AdjustMatrix[0]) { oneAtATime = true; } - } else if (cp.m_AdjustMatrix[1] != -cp.m_AdjustMatrix[2]) { - oneAtATime = true; } else { - useRSXform = true; + oneAtATime = true; } - } - *oneAtATimePtr = oneAtATime; - *scaleXPtr = oneAtATime ? 1 : scaleX; - return oneAtATime ? false : useRSXform; - } - - bool DrawText(pdfium::span<const TextCharPos> char_pos, - const CFX_Font* pFont, - const CFX_Matrix& matrix, - float font_size, - uint32_t color, - const CFX_TextRenderOptions& options) { - float scaleX = 1; - bool oneAtATime = false; - bool hasRSX = HasRSX(char_pos, &scaleX, &oneAtATime); - if (oneAtATime) { - return false; - } - - m_charDetails.SetCount(0); - m_rsxform.resize(0); - - const size_t original_count = m_charDetails.Count(); - FX_SAFE_SIZE_T safe_count = original_count; - safe_count += char_pos.size(); - const size_t total_count = safe_count.ValueOrDie(); - m_charDetails.SetCount(total_count); - if (hasRSX) - m_rsxform.resize(total_count); - - const SkScalar flip = font_size < 0 ? -1 : 1; - const SkScalar vFlip = pFont->IsVertical() ? -1 : 1; - for (size_t index = 0; index < char_pos.size(); ++index) { - const TextCharPos& cp = char_pos[index]; - size_t cur_index = index + original_count; - m_charDetails.SetPositionAt( - cur_index, {cp.m_Origin.x * flip, cp.m_Origin.y * vFlip}); - m_charDetails.SetGlyphAt(cur_index, - static_cast<uint16_t>(cp.m_GlyphIndex)); - m_charDetails.SetFontCharWidthAt(cur_index, cp.m_FontCharWidth); -#if BUILDFLAG(IS_APPLE) - if (cp.m_ExtGID) { - m_charDetails.SetGlyphAt(cur_index, static_cast<uint16_t>(cp.m_ExtGID)); - } -#endif - } - if (hasRSX) { - const DataVector<SkPoint>& positions = m_charDetails.GetPositions(); - for (size_t index = 0; index < char_pos.size(); ++index) { - const TextCharPos& cp = char_pos[index]; - SkRSXform& rsxform = m_rsxform[index + original_count]; - if (cp.m_bGlyphAdjust) { - rsxform.fSCos = cp.m_AdjustMatrix[0]; - rsxform.fSSin = cp.m_AdjustMatrix[1]; - rsxform.fTx = cp.m_AdjustMatrix[0] * positions[index].fX; - rsxform.fTy = -cp.m_AdjustMatrix[3] * positions[index].fY; - } else { - rsxform.fSCos = 1; - rsxform.fSSin = 0; - rsxform.fTx = positions[index].fX; - rsxform.fTy = positions[index].fY; - } - } - } - - SkPaint skPaint; - skPaint.setAntiAlias(true); - skPaint.setColor(color); - - SkFont font; - if (pFont->GetFaceRec()) { // exclude placeholder test fonts - font.setTypeface(sk_ref_sp(pFont->GetDeviceCache())); - } - font.setEmbolden(pFont->IsSubstFontBold()); - font.setHinting(SkFontHinting::kNone); - font.setScaleX(scaleX); - font.setSkewX(tanf(pFont->GetSubstFontItalicAngle() * FXSYS_PI / 180.0)); - font.setSize(SkTAbs(font_size)); - font.setSubpixel(true); - font.setEdging(GetFontEdgingType(options)); - - SkAutoCanvasRestore scoped_save_restore(m_pCanvas, /*doSave=*/true); - m_pCanvas->concat(ToFlippedSkMatrix(matrix, flip)); - - const DataVector<uint16_t>& glyphs = m_charDetails.GetGlyphs(); - if (m_rsxform.size()) { - sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromRSXform( - glyphs.data(), glyphs.size() * sizeof(uint16_t), m_rsxform.data(), - font, SkTextEncoding::kGlyphID); - m_pCanvas->drawTextBlob(blob, 0, 0, skPaint); + } else if (cp.m_AdjustMatrix[1] != -cp.m_AdjustMatrix[2]) { + oneAtATime = true; } else { - const DataVector<SkPoint>& positions = m_charDetails.GetPositions(); - for (size_t i = 0; i < m_charDetails.Count(); ++i) { - sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromText( - &glyphs[i], sizeof(glyphs[i]), font, SkTextEncoding::kGlyphID); - m_pCanvas->drawTextBlob(blob, positions[i].fX, positions[i].fY, - skPaint); - } + useRSXform = true; } - return true; } + *oneAtATimePtr = oneAtATime; + *scaleXPtr = oneAtATime ? 1 : scaleX; + return oneAtATime ? false : useRSXform; +} - private: - class CharDetail { - public: - CharDetail() = default; - ~CharDetail() = default; - - const DataVector<SkPoint>& GetPositions() const { return m_positions; } - void SetPositionAt(size_t index, const SkPoint& position) { - m_positions[index] = position; - } - const DataVector<uint16_t>& GetGlyphs() const { return m_glyphs; } - void SetGlyphAt(size_t index, uint16_t glyph) { m_glyphs[index] = glyph; } - const DataVector<uint32_t>& GetFontCharWidths() const { - return m_fontCharWidths; - } - void SetFontCharWidthAt(size_t index, uint32_t width) { - m_fontCharWidths[index] = width; - } - size_t Count() const { - DCHECK_EQ(m_positions.size(), m_glyphs.size()); - return m_glyphs.size(); - } - void SetCount(size_t count) { - m_positions.resize(count); - m_glyphs.resize(count); - m_fontCharWidths.resize(count); - } - - private: - DataVector<SkPoint> m_positions; // accumulator for text positions - DataVector<uint16_t> m_glyphs; // accumulator for text glyphs - // accumulator for glyphs' width defined in pdf - DataVector<uint32_t> m_fontCharWidths; - }; - - CharDetail m_charDetails; - // accumulator for txt rotate/scale/translate - DataVector<SkRSXform> m_rsxform; - UnownedPtr<SkCanvas> const m_pCanvas; -}; +} // namespace // static std::unique_ptr<CFX_SkiaDeviceDriver> CFX_SkiaDeviceDriver::Create( @@ -1019,13 +873,11 @@ skBitmap.installPixels(imageInfo, m_pBitmap->GetBuffer().data(), m_pBitmap->GetPitch()); m_pCanvas = new SkCanvas(skBitmap); - m_pCache = std::make_unique<SkiaState>(m_pCanvas); } CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(SkPictureRecorder* recorder) : m_pRecorder(recorder), m_bGroupKnockout(false) { m_pCanvas = m_pRecorder->getRecordingCanvas(); - m_pCache = std::make_unique<SkiaState>(m_pCanvas); int width = m_pCanvas->imageInfo().width(); int height = m_pCanvas->imageInfo().height(); DCHECK_EQ(kUnknown_SkColorType, m_pCanvas->imageInfo().colorType()); @@ -1051,7 +903,6 @@ } if (!m_pRecorder) { - m_pCache.reset(); delete m_pCanvas; } } @@ -1085,8 +936,8 @@ return false; } - if (m_pCache->DrawText(pCharPos, pFont, mtObject2Device, font_size, color, - options)) { + if (TryDrawText(pCharPos, pFont, mtObject2Device, font_size, color, + options)) { return true; } sk_sp<SkTypeface> typeface(SkSafeRef(pFont->GetDeviceCache())); @@ -1110,6 +961,8 @@ m_pCanvas->concat(skMatrix); DataVector<SkPoint> positions(pCharPos.size()); DataVector<uint16_t> glyphs(pCharPos.size()); + + // TODO(crbug.com/pdfium/1936): Reuse `HasRSX()` result. bool useRSXform = false; bool oneAtATime = false; for (size_t index = 0; index < pCharPos.size(); ++index) { @@ -1199,6 +1052,101 @@ return true; } +bool CFX_SkiaDeviceDriver::TryDrawText(pdfium::span<const TextCharPos> char_pos, + const CFX_Font* pFont, + const CFX_Matrix& matrix, + float font_size, + uint32_t color, + const CFX_TextRenderOptions& options) { + float scaleX = 1; + bool oneAtATime = false; + bool hasRSX = HasRSX(char_pos, &scaleX, &oneAtATime); + if (oneAtATime) { + return false; + } + + m_charDetails.SetCount(0); + m_rsxform.resize(0); + + const size_t original_count = m_charDetails.Count(); + FX_SAFE_SIZE_T safe_count = original_count; + safe_count += char_pos.size(); + const size_t total_count = safe_count.ValueOrDie(); + m_charDetails.SetCount(total_count); + if (hasRSX) { + m_rsxform.resize(total_count); + } + + const SkScalar flip = font_size < 0 ? -1 : 1; + const SkScalar vFlip = pFont->IsVertical() ? -1 : 1; + for (size_t index = 0; index < char_pos.size(); ++index) { + const TextCharPos& cp = char_pos[index]; + size_t cur_index = index + original_count; + m_charDetails.SetPositionAt(cur_index, + {cp.m_Origin.x * flip, cp.m_Origin.y * vFlip}); + m_charDetails.SetGlyphAt(cur_index, static_cast<uint16_t>(cp.m_GlyphIndex)); + m_charDetails.SetFontCharWidthAt(cur_index, cp.m_FontCharWidth); +#if BUILDFLAG(IS_APPLE) + if (cp.m_ExtGID) { + m_charDetails.SetGlyphAt(cur_index, static_cast<uint16_t>(cp.m_ExtGID)); + } +#endif + } + if (hasRSX) { + const DataVector<SkPoint>& positions = m_charDetails.GetPositions(); + for (size_t index = 0; index < char_pos.size(); ++index) { + const TextCharPos& cp = char_pos[index]; + SkRSXform& rsxform = m_rsxform[index + original_count]; + if (cp.m_bGlyphAdjust) { + rsxform.fSCos = cp.m_AdjustMatrix[0]; + rsxform.fSSin = cp.m_AdjustMatrix[1]; + rsxform.fTx = cp.m_AdjustMatrix[0] * positions[index].fX; + rsxform.fTy = -cp.m_AdjustMatrix[3] * positions[index].fY; + } else { + rsxform.fSCos = 1; + rsxform.fSSin = 0; + rsxform.fTx = positions[index].fX; + rsxform.fTy = positions[index].fY; + } + } + } + + SkPaint skPaint; + skPaint.setAntiAlias(true); + skPaint.setColor(color); + + SkFont font; + if (pFont->GetFaceRec()) { // exclude placeholder test fonts + font.setTypeface(sk_ref_sp(pFont->GetDeviceCache())); + } + font.setEmbolden(pFont->IsSubstFontBold()); + font.setHinting(SkFontHinting::kNone); + font.setScaleX(scaleX); + font.setSkewX(tanf(pFont->GetSubstFontItalicAngle() * FXSYS_PI / 180.0)); + font.setSize(SkTAbs(font_size)); + font.setSubpixel(true); + font.setEdging(GetFontEdgingType(options)); + + SkAutoCanvasRestore scoped_save_restore(m_pCanvas, /*doSave=*/true); + m_pCanvas->concat(ToFlippedSkMatrix(matrix, flip)); + + const DataVector<uint16_t>& glyphs = m_charDetails.GetGlyphs(); + if (m_rsxform.size()) { + sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromRSXform( + glyphs.data(), glyphs.size() * sizeof(uint16_t), m_rsxform.data(), font, + SkTextEncoding::kGlyphID); + m_pCanvas->drawTextBlob(blob, 0, 0, skPaint); + } else { + const DataVector<SkPoint>& positions = m_charDetails.GetPositions(); + for (size_t i = 0; i < m_charDetails.Count(); ++i) { + sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromText( + &glyphs[i], sizeof(glyphs[i]), font, SkTextEncoding::kGlyphID); + m_pCanvas->drawTextBlob(blob, positions[i].fX, positions[i].fY, skPaint); + } + } + return true; +} + int CFX_SkiaDeviceDriver::GetDriverType() const { return 1; } @@ -1857,6 +1805,9 @@ return true; } +CFX_SkiaDeviceDriver::CharDetail::CharDetail() = default; +CFX_SkiaDeviceDriver::CharDetail::~CharDetail() = default; + void CFX_DefaultRenderDevice::Clear(uint32_t color) { static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver())->Clear(color); }
diff --git a/core/fxge/skia/fx_skia_device.h b/core/fxge/skia/fx_skia_device.h index 876c20e..d18f0e0 100644 --- a/core/fxge/skia/fx_skia_device.h +++ b/core/fxge/skia/fx_skia_device.h
@@ -5,17 +5,31 @@ #ifndef CORE_FXGE_SKIA_FX_SKIA_DEVICE_H_ #define CORE_FXGE_SKIA_FX_SKIA_DEVICE_H_ +#include <stdint.h> + #include <memory> +#include "core/fxcrt/data_vector.h" +#include "core/fxcrt/fx_memory_wrappers.h" #include "core/fxcrt/retain_ptr.h" #include "core/fxge/cfx_fillrenderoptions.h" #include "core/fxge/cfx_path.h" #include "core/fxge/renderdevicedriver_iface.h" +#include "third_party/base/check_op.h" +#include "third_party/base/span.h" +#include "third_party/skia/include/core/SkPoint.h" +#include "third_party/skia/include/core/SkRSXform.h" +class CFX_Font; +class CFX_Matrix; class SkCanvas; class SkPictureRecorder; -class SkiaState; class TextCharPos; +struct CFX_TextRenderOptions; + +// Assumes Skia is not going to add non-data members to its fundamental types. +FX_DATA_PARTITION_EXCEPTION(SkPoint); +FX_DATA_PARTITION_EXCEPTION(SkRSXform); class CFX_SkiaDeviceDriver final : public RenderDeviceDriverIface { public: @@ -142,11 +156,52 @@ void Dump() const; private: + class CharDetail { + public: + CharDetail(); + ~CharDetail(); + + const DataVector<SkPoint>& GetPositions() const { return m_positions; } + void SetPositionAt(size_t index, const SkPoint& position) { + m_positions[index] = position; + } + const DataVector<uint16_t>& GetGlyphs() const { return m_glyphs; } + void SetGlyphAt(size_t index, uint16_t glyph) { m_glyphs[index] = glyph; } + const DataVector<uint32_t>& GetFontCharWidths() const { + return m_fontCharWidths; + } + void SetFontCharWidthAt(size_t index, uint32_t width) { + m_fontCharWidths[index] = width; + } + size_t Count() const { + DCHECK_EQ(m_positions.size(), m_glyphs.size()); + return m_glyphs.size(); + } + void SetCount(size_t count) { + m_positions.resize(count); + m_glyphs.resize(count); + m_fontCharWidths.resize(count); + } + + private: + DataVector<SkPoint> m_positions; // accumulator for text positions + DataVector<uint16_t> m_glyphs; // accumulator for text glyphs + // accumulator for glyphs' width defined in pdf + DataVector<uint32_t> m_fontCharWidths; + }; + CFX_SkiaDeviceDriver(RetainPtr<CFX_DIBitmap> pBitmap, bool bRgbByteOrder, RetainPtr<CFX_DIBitmap> pBackdropBitmap, bool bGroupKnockout); + bool TryDrawText(pdfium::span<const TextCharPos> char_pos, + const CFX_Font* pFont, + const CFX_Matrix& matrix, + float font_size, + uint32_t color, + const CFX_TextRenderOptions& options); + bool StartDIBitsSkia(const RetainPtr<CFX_DIBBase>& pBitmap, int bitmap_alpha, uint32_t color, @@ -163,10 +218,13 @@ SkCanvas* m_pCanvas; SkPictureRecorder* const m_pRecorder; - std::unique_ptr<SkiaState> m_pCache; CFX_FillRenderOptions m_FillOptions; bool m_bRgbByteOrder; bool m_bGroupKnockout; + + CharDetail m_charDetails; + // accumulator for txt rotate/scale/translate + DataVector<SkRSXform> m_rsxform; }; #endif // CORE_FXGE_SKIA_FX_SKIA_DEVICE_H_