You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
163 lines
4.6 KiB
163 lines
4.6 KiB
// Copyright 2017 PDFium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
|
|
|
|
#include "xfa/fgas/layout/cfx_break.h"
|
|
|
|
#include <algorithm>
|
|
#include <vector>
|
|
|
|
#include "core/fxcrt/fx_safe_types.h"
|
|
#include "third_party/base/stl_util.h"
|
|
#include "xfa/fgas/font/cfgas_gefont.h"
|
|
|
|
const float CFX_Break::kConversionFactor = 20000.0f;
|
|
const int CFX_Break::kMinimumTabWidth = 160000;
|
|
|
|
CFX_Break::CFX_Break(uint32_t dwLayoutStyles)
|
|
: m_dwLayoutStyles(dwLayoutStyles), m_pCurLine(&m_Lines[0]) {}
|
|
|
|
CFX_Break::~CFX_Break() = default;
|
|
|
|
void CFX_Break::Reset() {
|
|
m_eCharType = FX_CHARTYPE::kUnknown;
|
|
for (CFX_BreakLine& line : m_Lines)
|
|
line.Clear();
|
|
}
|
|
|
|
void CFX_Break::SetLayoutStyles(uint32_t dwLayoutStyles) {
|
|
m_dwLayoutStyles = dwLayoutStyles;
|
|
m_bSingleLine = (m_dwLayoutStyles & FX_LAYOUTSTYLE_SingleLine) != 0;
|
|
m_bCombText = (m_dwLayoutStyles & FX_LAYOUTSTYLE_CombText) != 0;
|
|
}
|
|
|
|
void CFX_Break::SetHorizontalScale(int32_t iScale) {
|
|
iScale = std::max(iScale, 0);
|
|
if (m_iHorizontalScale == iScale)
|
|
return;
|
|
|
|
SetBreakStatus();
|
|
m_iHorizontalScale = iScale;
|
|
}
|
|
|
|
void CFX_Break::SetVerticalScale(int32_t iScale) {
|
|
if (iScale < 0)
|
|
iScale = 0;
|
|
if (m_iVerticalScale == iScale)
|
|
return;
|
|
|
|
SetBreakStatus();
|
|
m_iVerticalScale = iScale;
|
|
}
|
|
|
|
void CFX_Break::SetFont(const RetainPtr<CFGAS_GEFont>& pFont) {
|
|
if (!pFont || pFont == m_pFont)
|
|
return;
|
|
|
|
SetBreakStatus();
|
|
m_pFont = pFont;
|
|
}
|
|
|
|
void CFX_Break::SetFontSize(float fFontSize) {
|
|
int32_t iFontSize = FXSYS_roundf(fFontSize * 20.0f);
|
|
if (m_iFontSize == iFontSize)
|
|
return;
|
|
|
|
SetBreakStatus();
|
|
m_iFontSize = iFontSize;
|
|
}
|
|
|
|
void CFX_Break::SetBreakStatus() {
|
|
++m_dwIdentity;
|
|
if (m_pCurLine->m_LineChars.empty())
|
|
return;
|
|
|
|
CFX_Char* tc = m_pCurLine->GetChar(m_pCurLine->m_LineChars.size() - 1);
|
|
if (tc->m_dwStatus == CFX_BreakType::None)
|
|
tc->m_dwStatus = CFX_BreakType::Piece;
|
|
}
|
|
|
|
bool CFX_Break::IsGreaterThanLineWidth(int32_t width) const {
|
|
FX_SAFE_INT32 line_width = m_iLineWidth;
|
|
line_width += m_iTolerance;
|
|
return line_width.IsValid() && width > line_width.ValueOrDie();
|
|
}
|
|
|
|
FX_CHARTYPE CFX_Break::GetUnifiedCharType(FX_CHARTYPE chartype) const {
|
|
return chartype >= FX_CHARTYPE::kArabicAlef ? FX_CHARTYPE::kArabic : chartype;
|
|
}
|
|
|
|
void CFX_Break::SetTabWidth(float fTabWidth) {
|
|
// Note, the use of max here was only done in the TxtBreak code. Leaving this
|
|
// in for the RTFBreak code for consistency. If we see issues with tab widths
|
|
// we may need to fix this.
|
|
m_iTabWidth =
|
|
std::max(FXSYS_roundf(fTabWidth * kConversionFactor), kMinimumTabWidth);
|
|
}
|
|
|
|
void CFX_Break::SetParagraphBreakChar(wchar_t wch) {
|
|
if (wch != L'\r' && wch != L'\n')
|
|
return;
|
|
m_wParagraphBreakChar = wch;
|
|
}
|
|
|
|
void CFX_Break::SetLineBreakTolerance(float fTolerance) {
|
|
m_iTolerance = FXSYS_roundf(fTolerance * kConversionFactor);
|
|
}
|
|
|
|
void CFX_Break::SetCharSpace(float fCharSpace) {
|
|
m_iCharSpace = FXSYS_roundf(fCharSpace * kConversionFactor);
|
|
}
|
|
|
|
void CFX_Break::SetLineBoundary(float fLineStart, float fLineEnd) {
|
|
if (fLineStart > fLineEnd)
|
|
return;
|
|
|
|
m_iLineStart = FXSYS_roundf(fLineStart * kConversionFactor);
|
|
m_iLineWidth = FXSYS_roundf(fLineEnd * kConversionFactor);
|
|
m_pCurLine->m_iStart = std::min(m_pCurLine->m_iStart, m_iLineWidth);
|
|
m_pCurLine->m_iStart = std::max(m_pCurLine->m_iStart, m_iLineStart);
|
|
}
|
|
|
|
CFX_Char* CFX_Break::GetLastChar(int32_t index,
|
|
bool bOmitChar,
|
|
bool bRichText) const {
|
|
std::vector<CFX_Char>& tca = m_pCurLine->m_LineChars;
|
|
if (!pdfium::IndexInBounds(tca, index))
|
|
return nullptr;
|
|
|
|
int32_t iStart = pdfium::CollectionSize<int32_t>(tca) - 1;
|
|
while (iStart > -1) {
|
|
CFX_Char* pTC = &tca[iStart--];
|
|
if (((bRichText && pTC->m_iCharWidth < 0) || bOmitChar) &&
|
|
pTC->GetCharType() == FX_CHARTYPE::kCombination) {
|
|
continue;
|
|
}
|
|
if (--index < 0)
|
|
return pTC;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
int32_t CFX_Break::CountBreakPieces() const {
|
|
return HasLine() ? pdfium::CollectionSize<int32_t>(
|
|
m_Lines[m_iReadyLineIndex].m_LinePieces)
|
|
: 0;
|
|
}
|
|
|
|
const CFX_BreakPiece* CFX_Break::GetBreakPieceUnstable(int32_t index) const {
|
|
if (!HasLine())
|
|
return nullptr;
|
|
if (!pdfium::IndexInBounds(m_Lines[m_iReadyLineIndex].m_LinePieces, index))
|
|
return nullptr;
|
|
return &m_Lines[m_iReadyLineIndex].m_LinePieces[index];
|
|
}
|
|
|
|
void CFX_Break::ClearBreakPieces() {
|
|
if (HasLine())
|
|
m_Lines[m_iReadyLineIndex].Clear();
|
|
m_iReadyLineIndex = -1;
|
|
}
|