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; }
/* 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; }