Beispiel #1
0
CPDF_TextPage::GenerateCharacter CPDF_TextPage::ProcessInsertObject(
    const CPDF_TextObject* pObj,
    const CFX_Matrix& formMatrix) {
  FindPreviousTextObject();
  TextOrientation WritingMode = GetTextObjectWritingMode(pObj);
  if (WritingMode == TextOrientation::Unknown)
    WritingMode = GetTextObjectWritingMode(m_pPreTextObj.Get());

  size_t nItem = m_pPreTextObj->CountItems();
  if (nItem == 0)
    return GenerateCharacter::None;

  CPDF_TextObjectItem PrevItem;
  m_pPreTextObj->GetItemInfo(nItem - 1, &PrevItem);

  CPDF_TextObjectItem item;
  pObj->GetItemInfo(0, &item);

  const CFX_FloatRect& this_rect = pObj->GetRect();
  const CFX_FloatRect& prev_rect = m_pPreTextObj->GetRect();

  WideString wstrItem = pObj->GetFont()->UnicodeFromCharCode(item.m_CharCode);
  if (wstrItem.IsEmpty())
    wstrItem += static_cast<wchar_t>(item.m_CharCode);
  wchar_t curChar = wstrItem[0];
  if (WritingMode == TextOrientation::Horizontal) {
    if (EndHorizontalLine(this_rect, prev_rect)) {
      return IsHyphen(curChar) ? GenerateCharacter::Hyphen
                               : GenerateCharacter::LineBreak;
    }
  } else if (WritingMode == TextOrientation::Vertical) {
    if (EndVerticalLine(this_rect, prev_rect, m_CurlineRect,
                        pObj->GetFontSize(), m_pPreTextObj->GetFontSize())) {
      return IsHyphen(curChar) ? GenerateCharacter::Hyphen
                               : GenerateCharacter::LineBreak;
    }
  }

  float last_pos = PrevItem.m_Origin.x;
  uint32_t nLastWidth =
      GetCharWidth(PrevItem.m_CharCode, m_pPreTextObj->GetFont());
  float last_width = nLastWidth * m_pPreTextObj->GetFontSize() / 1000;
  last_width = fabs(last_width);
  uint32_t nThisWidth = GetCharWidth(item.m_CharCode, pObj->GetFont());
  float this_width = fabs(nThisWidth * pObj->GetFontSize() / 1000);
  float threshold = std::max(last_width, this_width) / 4;

  CFX_Matrix prev_matrix = m_pPreTextObj->GetTextMatrix() * m_perMatrix;
  CFX_Matrix prev_reverse = prev_matrix.GetInverse();

  CFX_PointF pos = prev_reverse.Transform(formMatrix.Transform(pObj->GetPos()));
  if (last_width < this_width)
    threshold = prev_reverse.TransformDistance(threshold);

  bool bNewline = false;
  if (WritingMode == TextOrientation::Horizontal) {
    CFX_FloatRect rect = m_pPreTextObj->GetRect();
    float rect_height = rect.Height();
    rect.Normalize();
    if ((rect.IsEmpty() && rect_height > 5) ||
        ((pos.y > threshold * 2 || pos.y < threshold * -3) &&
         (fabs(pos.y) >= 1 || fabs(pos.y) > fabs(pos.x)))) {
      bNewline = true;
      if (nItem > 1) {
        CPDF_TextObjectItem tempItem;
        m_pPreTextObj->GetItemInfo(0, &tempItem);
        CFX_Matrix m = m_pPreTextObj->GetTextMatrix();
        if (PrevItem.m_Origin.x > tempItem.m_Origin.x &&
            m_DisplayMatrix.a > 0.9 && m_DisplayMatrix.b < 0.1 &&
            m_DisplayMatrix.c < 0.1 && m_DisplayMatrix.d < -0.9 && m.b < 0.1 &&
            m.c < 0.1) {
          CFX_FloatRect re(0, m_pPreTextObj->GetRect().bottom, 1000,
                           m_pPreTextObj->GetRect().top);
          if (re.Contains(pObj->GetPos())) {
            bNewline = false;
          } else {
            if (CFX_FloatRect(0, pObj->GetRect().bottom, 1000,
                              pObj->GetRect().top)
                    .Contains(m_pPreTextObj->GetPos())) {
              bNewline = false;
            }
          }
        }
      }
    }
  }
  if (bNewline) {
    return IsHyphen(curChar) ? GenerateCharacter::Hyphen
                             : GenerateCharacter::LineBreak;
  }

  if (pObj->CountChars() == 1 && IsHyphenCode(curChar) && IsHyphen(curChar))
    return GenerateCharacter::Hyphen;

  if (curChar == L' ')
    return GenerateCharacter::None;

  WideString PrevStr =
      m_pPreTextObj->GetFont()->UnicodeFromCharCode(PrevItem.m_CharCode);
  wchar_t preChar = PrevStr.Last();
  if (preChar == L' ')
    return GenerateCharacter::None;

  CFX_Matrix matrix = pObj->GetTextMatrix() * formMatrix;
  float threshold2 = static_cast<float>(std::max(nLastWidth, nThisWidth));
  threshold2 = NormalizeThreshold(threshold2, 400, 700, 800);
  if (nLastWidth >= nThisWidth) {
    threshold2 *= fabs(m_pPreTextObj->GetFontSize());
  } else {
    threshold2 *= fabs(pObj->GetFontSize());
    threshold2 = matrix.TransformDistance(threshold2);
    threshold2 = prev_reverse.TransformDistance(threshold2);
  }
  threshold2 /= 1000;
  if ((threshold2 < 1.4881 && threshold2 > 1.4879) ||
      (threshold2 < 1.39001 && threshold2 > 1.38999)) {
    threshold2 *= 1.5;
  }
  return GenerateSpace(pos, last_pos, this_width, last_width, threshold2)
             ? GenerateCharacter::Space
             : GenerateCharacter::None;
}
Beispiel #2
0
/*
HP1-HP2
Дефисной группой считается последовательность графематических слов, разделенных 
дефисом,например:
  красно-зеленый
  Комсомольск-на-Амуре
  В дефисной группе запрещены пробелы, но могут попадаться концы строк.
  Дефис с пробелами считается тире.
  Эта функция находит дефисные пары, и если начало дефисной пары совпадает 
  с концом предыдущей дефисной  пары,   тогда объединяет эти пары в одну группу
*/
int CGraphmatFile::DealHyphenPaar (size_t i,  size_t HB)
{
	size_t nh,nt;
	bool fl_spc=false;
	if (i==0) return false;
	if (!IsHyphen(i)) return false;

	for (nh=i-1;  nh>0 && GetUnits()[nh].IsSoft(); nh--)
		fl_spc = fl_spc || GetUnits()[nh].IsSpace ();

	for (nt=i+1;  nt<HB && GetUnits()[nt].IsSoft(); nt++)
		fl_spc = fl_spc || GetUnits()[nt].IsSpace ();

	if (  !fl_spc 
		&& nh > 0 
		&& nt < HB 
		&& (HasDescr (nh,ORLE) || HasDescr (nh,OLLE))
		&& (HasDescr (nt,ORLE) || HasDescr (nt,OLLE))
		)
	{ 

		/*
		если начало дефисной группы совпадает с концом предыдущей дефисной  группы,
		тогда нужно объединить эти группы, например:
		Комсомольск-на-Амуре
		Но кол-во дефисов в группе не должно быть больше трех (ad-hoc)
		*/
		if (HasDescr (nh,OSHyp2))
		{
			int i;
			for (i=nh-1; i > 0; i--)
				if (HasDescr (i,OSHyp1) )
					break;
			if (nt - i <= 4) // четыре слова - это три дефиса
			{
				DeleteDescr(nh,OSHyp2);
				nh = i;
				SetDes (nt,OSHyp2);
			}
			else
				return false;
		}
		else
		{
			SetDes (nh,OSHyp1);
			SetDes (nt,OSHyp2);
		};

		// если в дефисную группу попал однословный  оборот, то нужно отменить его,  например, может быть найден 
		// оборот ЗГЛ=что  в дефисной группе что-нибудь. 

		long l=nh;
		for (;  l<=nt; l++)
			if (	   HasDescr (l,OOb1) 
				&& HasDescr (l,OOb2) 
			 )
			{
				DeleteDescr(l,OOb1);
				DeleteDescr(l,OOb2);

				SetOborotNo(l, -1);
			};
		// если в дефисная группа пересекается  с оборотом, но оборот не вкладывает ее и не вкладывается в нее,
		// тогда  нужно отменить дефисныую группу. Я это видеол только на ошибочном примере "бригад-тем не менее"
		// это какая-та ошибка  при сканировании, но лучше ее обработать, иначе валится синтаксис
		bool bInOborot = false;
		for (l=nh;  l<=nt; l++)
		{
			if ( HasDescr (l,OOb1)  )
			{
				bInOborot = true;
			};

			if	(HasDescr (l,OOb2)  )
			{
				if (		(!bInOborot)
					&&	( l<nt)
					)
				{
					bInOborot = true;
					break;
				};
				bInOborot = false;
			};
		};
		if (bInOborot)
		{
			DeleteDescr(nh,OSHyp1);
			DeleteDescr(nt,OSHyp2);

			return false;
		};

		return true; 
	}

	return false;
}