本文整理汇总了C++中CFX_AffineMatrix类的典型用法代码示例。如果您正苦于以下问题:C++ CFX_AffineMatrix类的具体用法?C++ CFX_AffineMatrix怎么用?C++ CFX_AffineMatrix使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了CFX_AffineMatrix类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: Transform
void CPDF_ShadingObject::Transform(const CFX_AffineMatrix& matrix)
{
if (!m_ClipPath.IsNull()) {
m_ClipPath.GetModify();
m_ClipPath.Transform(matrix);
}
m_Matrix.Concat(matrix);
if (!m_ClipPath.IsNull()) {
CalcBoundingBox();
} else {
matrix.TransformRect(m_Left, m_Right, m_Top, m_Bottom);
}
}
示例2: GetDisplayMatrix
void CPDF_Page::GetDisplayMatrix(CFX_AffineMatrix& matrix, int xPos, int yPos,
int xSize, int ySize, int iRotate) const
{
if (m_PageWidth == 0 || m_PageHeight == 0) {
return;
}
CFX_AffineMatrix display_matrix;
int x0, y0, x1, y1, x2, y2;
iRotate %= 4;
switch (iRotate) {
case 0:
x0 = xPos;
y0 = yPos + ySize;
x1 = xPos;
y1 = yPos;
x2 = xPos + xSize;
y2 = yPos + ySize;
break;
case 1:
x0 = xPos;
y0 = yPos;
x1 = xPos + xSize;
y1 = yPos;
x2 = xPos;
y2 = yPos + ySize;
break;
case 2:
x0 = xPos + xSize;
y0 = yPos;
x1 = xPos + xSize;
y1 = yPos + ySize;
x2 = xPos;
y2 = yPos;
break;
case 3:
x0 = xPos + xSize;
y0 = yPos + ySize;
x1 = xPos;
y1 = yPos + ySize;
x2 = xPos + xSize;
y2 = yPos;
break;
}
display_matrix.Set(FXSYS_Div((FX_FLOAT)(x2 - x0), m_PageWidth),
FXSYS_Div((FX_FLOAT)(y2 - y0), m_PageWidth),
FXSYS_Div((FX_FLOAT)(x1 - x0), m_PageHeight),
FXSYS_Div((FX_FLOAT)(y1 - y0), m_PageHeight),
(FX_FLOAT)x0, (FX_FLOAT)y0);
matrix = m_PageMatrix;
matrix.Concat(display_matrix);
}
示例3: FPDFDOC_GetAnnotAP
void CPDF_FormControl::DrawControl(CFX_RenderDevice* pDevice, CFX_AffineMatrix* pMatrix, CPDF_Page* pPage,
CPDF_Annot::AppearanceMode mode, const CPDF_RenderOptions* pOptions)
{
if (m_pWidgetDict->GetInteger("F") & ANNOTFLAG_HIDDEN) {
return;
}
CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(m_pWidgetDict, mode);
if (pStream == NULL) {
return;
}
CFX_FloatRect form_bbox = pStream->GetDict()->GetRect("BBox");
CFX_AffineMatrix form_matrix = pStream->GetDict()->GetMatrix("Matrix");
form_matrix.TransformRect(form_bbox);
CFX_FloatRect arect = m_pWidgetDict->GetRect("Rect");
CFX_AffineMatrix matrix;
matrix.MatchRect(arect, form_bbox);
matrix.Concat(*pMatrix);
CPDF_Form form(m_pField->m_pForm->m_pDocument, m_pField->m_pForm->m_pFormDict->GetDict("DR"), pStream);
form.ParseContent(NULL, NULL, NULL, NULL);
CPDF_RenderContext context;
context.Create(pPage);
context.DrawObjectList(pDevice, &form, &matrix, pOptions);
}
示例4: GetMatrix
CFX_AffineMatrix GetMatrix(CPDF_Rect rcAnnot, CPDF_Rect rcStream, CFX_AffineMatrix matrix)
{
if(rcStream.IsEmpty())
return CFX_AffineMatrix();
matrix.TransformRect(rcStream);
rcStream.Normalize();
FX_FLOAT a = rcAnnot.Width()/rcStream.Width();
FX_FLOAT d = rcAnnot.Height()/rcStream.Height();
FX_FLOAT e = rcAnnot.left - rcStream.left * a;
FX_FLOAT f = rcAnnot.bottom - rcStream.bottom * d;
return CFX_AffineMatrix(a, 0, 0, d, e, f);
}
示例5: DrawPatternBitmap
static CFX_DIBitmap* DrawPatternBitmap(CPDF_Document* pDoc,
CPDF_PageRenderCache* pCache,
CPDF_TilingPattern* pPattern,
const CFX_AffineMatrix* pObject2Device,
int width,
int height,
int flags) {
CFX_DIBitmap* pBitmap = new CFX_DIBitmap;
if (!pBitmap->Create(width, height,
pPattern->m_bColored ? FXDIB_Argb : FXDIB_8bppMask)) {
delete pBitmap;
return NULL;
}
CFX_FxgeDevice bitmap_device;
bitmap_device.Attach(pBitmap);
pBitmap->Clear(0);
CFX_FloatRect cell_bbox = pPattern->m_BBox;
pPattern->m_Pattern2Form.TransformRect(cell_bbox);
pObject2Device->TransformRect(cell_bbox);
CFX_FloatRect bitmap_rect(0.0f, 0.0f, (FX_FLOAT)width, (FX_FLOAT)height);
CFX_AffineMatrix mtAdjust;
mtAdjust.MatchRect(bitmap_rect, cell_bbox);
CFX_AffineMatrix mtPattern2Bitmap = *pObject2Device;
mtPattern2Bitmap.Concat(mtAdjust);
CPDF_RenderOptions options;
if (!pPattern->m_bColored) {
options.m_ColorMode = RENDER_COLOR_ALPHA;
}
flags |= RENDER_FORCE_HALFTONE;
options.m_Flags = flags;
CPDF_RenderContext context;
context.Create(pDoc, pCache, NULL);
context.DrawObjectList(&bitmap_device, pPattern->m_pForm, &mtPattern2Bitmap,
&options);
return pBitmap;
}
示例6: FocusGetPosition
FX_BOOL CPDF_ReflowedPage::FocusGetPosition(const CFX_AffineMatrix matrix, CFX_ByteString str, FX_INT32& x, FX_INT32& y)
{
if (NULL == m_pReflowed) {
return FALSE;
}
FX_INT32 pos = FXSYS_atoi(str);
if(pos < 0 || pos >= m_pReflowed->GetSize()) {
return FALSE;
}
CRF_Data* pData = (*m_pReflowed)[pos];
FX_FLOAT x1, y1;
matrix.Transform(pData->m_PosX, pData->m_PosY + pData->m_Height, x1, y1);
x = (int)x1;
y = (int)y1;
return TRUE;
}
示例7: FXSYS_fabs
FX_BOOL CPDF_RenderStatus::ProcessType3Text(const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device)
{
CPDF_Type3Font* pType3Font = textobj->m_TextState.GetFont()->GetType3Font();
for (int j = 0; j < m_Type3FontCache.GetSize(); j++)
if ((CPDF_Type3Font*)m_Type3FontCache.GetAt(j) == pType3Font) {
return TRUE;
}
CFX_Matrix dCTM = m_pDevice->GetCTM();
FX_FLOAT sa = FXSYS_fabs(dCTM.a);
FX_FLOAT sd = FXSYS_fabs(dCTM.d);
CFX_AffineMatrix text_matrix;
textobj->GetTextMatrix(&text_matrix);
CFX_AffineMatrix char_matrix = pType3Font->GetFontMatrix();
FX_FLOAT font_size = textobj->m_TextState.GetFontSize();
char_matrix.Scale(font_size, font_size);
FX_ARGB fill_argb = GetFillArgb(textobj, TRUE);
int fill_alpha = FXARGB_A(fill_argb);
int device_class = m_pDevice->GetDeviceClass();
FXTEXT_GLYPHPOS* pGlyphAndPos = NULL;
if (device_class == FXDC_DISPLAY) {
pGlyphAndPos = FX_Alloc(FXTEXT_GLYPHPOS, textobj->m_nChars);
} else if (fill_alpha < 255) {
return FALSE;
}
CPDF_RefType3Cache refTypeCache(pType3Font);
FX_DWORD *pChars = textobj->m_pCharCodes;
if (textobj->m_nChars == 1) {
pChars = (FX_DWORD*)(&textobj->m_pCharCodes);
}
for (int iChar = 0; iChar < textobj->m_nChars; iChar ++) {
FX_DWORD charcode = pChars[iChar];
if (charcode == (FX_DWORD) - 1) {
continue;
}
CPDF_Type3Char* pType3Char = pType3Font->LoadChar(charcode);
if (pType3Char == NULL) {
continue;
}
CFX_AffineMatrix matrix = char_matrix;
matrix.e += iChar ? textobj->m_pCharPos[iChar - 1] : 0;
matrix.Concat(text_matrix);
matrix.Concat(*pObj2Device);
if (!pType3Char->LoadBitmap(m_pContext)) {
if (pGlyphAndPos) {
for (int i = 0; i < iChar; i ++) {
FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[i];
if (glyph.m_pGlyph == NULL) {
continue;
}
m_pDevice->SetBitMask(&glyph.m_pGlyph->m_Bitmap,
glyph.m_OriginX + glyph.m_pGlyph->m_Left,
glyph.m_OriginY - glyph.m_pGlyph->m_Top, fill_argb);
}
FX_Free(pGlyphAndPos);
pGlyphAndPos = NULL;
}
CPDF_GraphicStates* pStates = CloneObjStates(textobj, FALSE);
CPDF_RenderOptions Options = m_Options;
Options.m_Flags |= RENDER_FORCE_HALFTONE | RENDER_RECT_AA;
Options.m_Flags &= ~RENDER_FORCE_DOWNSAMPLE;
CPDF_Dictionary* pFormResource = NULL;
if (pType3Char->m_pForm && pType3Char->m_pForm->m_pFormDict) {
pFormResource = pType3Char->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources"));
}
if (fill_alpha == 255) {
CPDF_RenderStatus status;
status.Initialize(m_Level + 1, m_pContext, m_pDevice, NULL, NULL, this, pStates, &Options,
pType3Char->m_pForm->m_Transparency, m_bDropObjects, pFormResource, FALSE, pType3Char, fill_argb);
status.m_Type3FontCache.Append(m_Type3FontCache);
status.m_Type3FontCache.Add(pType3Font);
m_pDevice->SaveState();
status.RenderObjectList(pType3Char->m_pForm, &matrix);
m_pDevice->RestoreState();
} else {
CFX_FloatRect rect_f = pType3Char->m_pForm->CalcBoundingBox();
rect_f.Transform(&matrix);
FX_RECT rect = rect_f.GetOutterRect();
CFX_FxgeDevice bitmap_device;
if (!bitmap_device.Create((int)(rect.Width() * sa), (int)(rect.Height() * sd), FXDIB_Argb)) {
return TRUE;
}
bitmap_device.GetBitmap()->Clear(0);
CPDF_RenderStatus status;
status.Initialize(m_Level + 1, m_pContext, &bitmap_device, NULL, NULL, this, pStates, &Options,
pType3Char->m_pForm->m_Transparency, m_bDropObjects, pFormResource, FALSE, pType3Char, fill_argb);
status.m_Type3FontCache.Append(m_Type3FontCache);
status.m_Type3FontCache.Add(pType3Font);
matrix.TranslateI(-rect.left, -rect.top);
matrix.Scale(sa, sd);
status.RenderObjectList(pType3Char->m_pForm, &matrix);
m_pDevice->SetDIBits(bitmap_device.GetBitmap(), rect.left, rect.top);
}
delete pStates;
} else if (pType3Char->m_pBitmap) {
if (device_class == FXDC_DISPLAY) {
CPDF_Type3Cache* pCache = GetCachedType3(pType3Font);
refTypeCache.m_dwCount++;
CFX_GlyphBitmap* pBitmap = pCache->LoadGlyph(charcode, &matrix, sa, sd);
if (pBitmap == NULL) {
continue;
//.........这里部分代码省略.........
示例8: FPDFPage_TransFormWithClip
DLLEXPORT FPDF_BOOL STDCALL FPDFPage_TransFormWithClip(FPDF_PAGE page, FS_MATRIX* matrix, FS_RECTF* clipRect)
{
if(!page)
return FALSE;
CFX_ByteTextBuf textBuf;
textBuf<<"q ";
CFX_FloatRect rect(clipRect->left, clipRect->bottom, clipRect->right, clipRect->top);
rect.Normalize();
CFX_ByteString bsClipping;
bsClipping.Format("%f %f %f %f re W* n ", rect.left, rect.bottom, rect.Width(), rect.Height());
textBuf<<bsClipping;
CFX_ByteString bsMatix;
bsMatix.Format("%f %f %f %f %f %f cm ", matrix->a, matrix->b,matrix->c,matrix->d,matrix->e,matrix->f);
textBuf<<bsMatix;
CPDF_Page* pPage = (CPDF_Page*)page;
CPDF_Dictionary* pPageDic = pPage->m_pFormDict;
CPDF_Object* pContentObj = pPageDic->GetElement("Contents");
if(!pContentObj)
pContentObj = pPageDic->GetArray("Contents");
if(!pContentObj)
return FALSE;
CPDF_Dictionary* pDic = FX_NEW CPDF_Dictionary;
CPDF_Stream* pStream = FX_NEW CPDF_Stream(NULL,0, pDic);
pStream->SetData(textBuf.GetBuffer(), textBuf.GetSize(), FALSE, FALSE);
CPDF_Document* pDoc = pPage->m_pDocument;
if(!pDoc)
return FALSE;
pDoc->AddIndirectObject(pStream);
pDic = FX_NEW CPDF_Dictionary;
CPDF_Stream* pEndStream = FX_NEW CPDF_Stream(NULL,0, pDic);
pEndStream->SetData((FX_LPCBYTE)" Q", 2, FALSE, FALSE);
pDoc->AddIndirectObject(pEndStream);
CPDF_Array* pContentArray = NULL;
if (pContentObj && pContentObj->GetType() == PDFOBJ_ARRAY)
{
pContentArray = (CPDF_Array*)pContentObj;
CPDF_Reference* pRef = FX_NEW CPDF_Reference(pDoc, pStream->GetObjNum());
pContentArray->InsertAt(0, pRef);
pContentArray->AddReference(pDoc,pEndStream);
}
else if(pContentObj && pContentObj->GetType() == PDFOBJ_REFERENCE)
{
CPDF_Reference* pReference = (CPDF_Reference*)pContentObj;
CPDF_Object* pDirectObj = pReference->GetDirect();
if(pDirectObj != NULL)
{
if(pDirectObj->GetType() == PDFOBJ_ARRAY)
{
pContentArray = (CPDF_Array*)pDirectObj;
CPDF_Reference* pRef = FX_NEW CPDF_Reference(pDoc, pStream->GetObjNum());
pContentArray->InsertAt(0, pRef);
pContentArray->AddReference(pDoc,pEndStream);
}
else if(pDirectObj->GetType() == PDFOBJ_STREAM)
{
pContentArray = FX_NEW CPDF_Array();
pContentArray->AddReference(pDoc,pStream->GetObjNum());
pContentArray->AddReference(pDoc,pDirectObj->GetObjNum());
pContentArray->AddReference(pDoc, pEndStream);
pPageDic->SetAtReference("Contents", pDoc, pDoc->AddIndirectObject(pContentArray));
}
}
}
//Need to transform the patterns as well.
CPDF_Dictionary* pRes = pPageDic->GetDict(FX_BSTRC("Resources"));
if(pRes)
{
CPDF_Dictionary* pPattenDict = pRes->GetDict(FX_BSTRC("Pattern"));
if(pPattenDict)
{
FX_POSITION pos = pPattenDict->GetStartPos();
while(pos)
{
CPDF_Dictionary* pDict = NULL;
CFX_ByteString key;
CPDF_Object* pObj = pPattenDict->GetNextElement(pos, key);
if(pObj->GetType() == PDFOBJ_REFERENCE)
pObj = pObj->GetDirect();
if(pObj->GetType() == PDFOBJ_DICTIONARY)
{
pDict = (CPDF_Dictionary*)pObj;
}
else if(pObj->GetType() == PDFOBJ_STREAM)
{
pDict = ((CPDF_Stream*)pObj)->GetDict();
}
else
continue;
CFX_AffineMatrix m = pDict->GetMatrix(FX_BSTRC("Matrix"));
//.........这里部分代码省略.........
示例9: FX_BSTRC
CFX_DIBitmap* CPDF_RenderStatus::LoadSMask(CPDF_Dictionary* pSMaskDict,
FX_RECT* pClipRect,
const CFX_AffineMatrix* pMatrix) {
if (pSMaskDict == NULL) {
return NULL;
}
int width = pClipRect->right - pClipRect->left;
int height = pClipRect->bottom - pClipRect->top;
FX_BOOL bLuminosity = FALSE;
bLuminosity = pSMaskDict->GetConstString(FX_BSTRC("S")) != FX_BSTRC("Alpha");
CPDF_Stream* pGroup = pSMaskDict->GetStream(FX_BSTRC("G"));
if (pGroup == NULL) {
return NULL;
}
nonstd::unique_ptr<CPDF_Function> pFunc;
CPDF_Object* pFuncObj = pSMaskDict->GetElementValue(FX_BSTRC("TR"));
if (pFuncObj && (pFuncObj->IsDictionary() || pFuncObj->IsStream()))
pFunc.reset(CPDF_Function::Load(pFuncObj));
CFX_AffineMatrix matrix = *pMatrix;
matrix.TranslateI(-pClipRect->left, -pClipRect->top);
CPDF_Form form(m_pContext->m_pDocument, m_pContext->m_pPageResources, pGroup);
form.ParseContent(NULL, NULL, NULL, NULL);
CFX_FxgeDevice bitmap_device;
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
if (!bitmap_device.Create(width, height,
bLuminosity ? FXDIB_Rgb32 : FXDIB_8bppMask)) {
return NULL;
}
#else
if (!bitmap_device.Create(width, height,
bLuminosity ? FXDIB_Rgb : FXDIB_8bppMask)) {
return NULL;
}
#endif
CFX_DIBitmap& bitmap = *bitmap_device.GetBitmap();
CPDF_Object* pCSObj = NULL;
CPDF_ColorSpace* pCS = NULL;
if (bLuminosity) {
CPDF_Array* pBC = pSMaskDict->GetArray(FX_BSTRC("BC"));
FX_ARGB back_color = 0xff000000;
if (pBC) {
CPDF_Dictionary* pDict = pGroup->GetDict();
if (pDict && pDict->GetDict(FX_BSTRC("Group")))
pCSObj =
pDict->GetDict(FX_BSTRC("Group"))->GetElementValue(FX_BSTRC("CS"));
else
pCSObj = NULL;
pCS = m_pContext->m_pDocument->LoadColorSpace(pCSObj);
if (pCS) {
FX_FLOAT R, G, B;
FX_DWORD comps = 8;
if (pCS->CountComponents() > static_cast<int32_t>(comps)) {
comps = (FX_DWORD)pCS->CountComponents();
}
CFX_FixedBufGrow<FX_FLOAT, 8> float_array(comps);
FX_FLOAT* pFloats = float_array;
FX_SAFE_DWORD num_floats = comps;
num_floats *= sizeof(FX_FLOAT);
if (!num_floats.IsValid()) {
return NULL;
}
FXSYS_memset(pFloats, 0, num_floats.ValueOrDie());
int count = pBC->GetCount() > 8 ? 8 : pBC->GetCount();
for (int i = 0; i < count; i++) {
pFloats[i] = pBC->GetNumber(i);
}
pCS->GetRGB(pFloats, R, G, B);
back_color = 0xff000000 | ((int32_t)(R * 255) << 16) |
((int32_t)(G * 255) << 8) | (int32_t)(B * 255);
m_pContext->m_pDocument->GetPageData()->ReleaseColorSpace(pCSObj);
}
}
bitmap.Clear(back_color);
} else {
bitmap.Clear(0);
}
CPDF_Dictionary* pFormResource = NULL;
if (form.m_pFormDict) {
pFormResource = form.m_pFormDict->GetDict(FX_BSTRC("Resources"));
}
CPDF_RenderOptions options;
options.m_ColorMode = bLuminosity ? RENDER_COLOR_NORMAL : RENDER_COLOR_ALPHA;
CPDF_RenderStatus status;
status.Initialize(m_pContext, &bitmap_device, NULL, NULL, NULL, NULL,
&options, 0, m_bDropObjects, pFormResource, TRUE, NULL, 0,
pCS ? pCS->GetFamily() : 0, bLuminosity);
status.RenderObjectList(&form, &matrix);
nonstd::unique_ptr<CFX_DIBitmap> pMask(new CFX_DIBitmap);
if (!pMask->Create(width, height, FXDIB_8bppMask))
return nullptr;
uint8_t* dest_buf = pMask->GetBuffer();
int dest_pitch = pMask->GetPitch();
uint8_t* src_buf = bitmap.GetBuffer();
int src_pitch = bitmap.GetPitch();
std::vector<uint8_t> transfers(256);
if (pFunc) {
CFX_FixedBufGrow<FX_FLOAT, 16> results(pFunc->CountOutputs());
for (int i = 0; i < 256; i++) {
//.........这里部分代码省略.........
示例10: FX_Alloc
void CTextPage::ProcessObject(CPDF_PageObject* pObject)
{
if (pObject->m_Type != PDFPAGE_TEXT) {
return;
}
CPDF_TextObject* pText = (CPDF_TextObject*)pObject;
CPDF_Font* pFont = pText->m_TextState.GetFont();
int count = pText->CountItems();
FX_FLOAT* pPosArray = FX_Alloc(FX_FLOAT, count * 2);
if (pPosArray) {
pText->CalcCharPos(pPosArray);
}
FX_FLOAT fontsize_h = pText->m_TextState.GetFontSizeH();
FX_FLOAT fontsize_v = pText->m_TextState.GetFontSizeV();
FX_DWORD space_charcode = pFont->CharCodeFromUnicode(' ');
FX_FLOAT spacew = 0;
if (space_charcode != -1) {
spacew = fontsize_h * pFont->GetCharWidthF(space_charcode) / 1000;
}
if (spacew == 0) {
spacew = fontsize_h / 4;
}
if (pText->m_TextState.GetBaselineAngle() != 0) {
int cc = 0;
CFX_AffineMatrix matrix;
pText->GetTextMatrix(&matrix);
for (int i = 0; i < pText->m_nChars; i ++) {
FX_DWORD charcode = pText->m_nChars == 1 ? (FX_DWORD)(FX_UINTPTR)pText->m_pCharCodes : pText->m_pCharCodes[i];
if (charcode == (FX_DWORD) - 1) {
continue;
}
FX_RECT char_box;
pFont->GetCharBBox(charcode, char_box);
FX_FLOAT char_left = pPosArray ? pPosArray[cc * 2] : char_box.left * pText->m_TextState.GetFontSize() / 1000;
FX_FLOAT char_right = pPosArray ? pPosArray[cc * 2 + 1] : char_box.right * pText->m_TextState.GetFontSize() / 1000;
FX_FLOAT char_top = char_box.top * pText->m_TextState.GetFontSize() / 1000;
FX_FLOAT char_bottom = char_box.bottom * pText->m_TextState.GetFontSize() / 1000;
cc ++;
FX_FLOAT char_origx, char_origy;
matrix.Transform(char_left, 0, char_origx, char_origy);
matrix.TransformRect(char_left, char_right, char_top, char_bottom);
CFX_ByteString str;
pFont->AppendChar(str, charcode);
InsertTextBox(NULL, char_origy, char_left, char_right, char_top,
char_bottom, spacew, fontsize_v, str, pFont);
}
if (pPosArray) {
FX_Free(pPosArray);
}
return;
}
FX_FLOAT ratio_h = fontsize_h / pText->m_TextState.GetFontSize();
for (int ii = 0; ii < count * 2; ii ++) {
pPosArray[ii] *= ratio_h;
}
FX_FLOAT baseline = pText->m_PosY;
CTextBaseLine* pBaseLine = NULL;
FX_FLOAT topy = pText->m_Top;
FX_FLOAT bottomy = pText->m_Bottom;
FX_FLOAT leftx = pText->m_Left;
int cc = 0;
CFX_ByteString segment;
int space_count = 0;
FX_FLOAT last_left = 0, last_right = 0, segment_left = 0, segment_right = 0;
for (int i = 0; i < pText->m_nChars; i ++) {
FX_DWORD charcode = pText->m_nChars == 1 ? (FX_DWORD)(FX_UINTPTR)pText->m_pCharCodes : pText->m_pCharCodes[i];
if (charcode == (FX_DWORD) - 1) {
continue;
}
FX_FLOAT char_left = pPosArray[cc * 2];
FX_FLOAT char_right = pPosArray[cc * 2 + 1];
cc ++;
if (char_left < last_left || (char_left - last_right) > spacew / 2) {
pBaseLine = InsertTextBox(pBaseLine, baseline, leftx + segment_left, leftx + segment_right,
topy, bottomy, spacew, fontsize_v, segment, pFont);
segment_left = char_left;
segment = "";
}
if (space_count > 1) {
pBaseLine = InsertTextBox(pBaseLine, baseline, leftx + segment_left, leftx + segment_right,
topy, bottomy, spacew, fontsize_v, segment, pFont);
segment = "";
} else if (space_count == 1) {
pFont->AppendChar(segment, ' ');
}
if (segment.GetLength() == 0) {
segment_left = char_left;
}
segment_right = char_right;
pFont->AppendChar(segment, charcode);
space_count = 0;
last_left = char_left;
last_right = char_right;
}
if (segment.GetLength())
pBaseLine = InsertTextBox(pBaseLine, baseline, leftx + segment_left, leftx + segment_right,
topy, bottomy, spacew, fontsize_v, segment, pFont);
FX_Free(pPosArray);
}
示例11: FXSYS_Mul
//.........这里部分代码省略.........
}
if (min_y > char_rect.bottom) {
min_y = (FX_FLOAT)char_rect.bottom;
}
if (max_y < char_rect.bottom) {
max_y = (FX_FLOAT)char_rect.bottom;
}
FX_FLOAT char_left = curpos + char_rect.left * fontsize / 1000;
FX_FLOAT char_right = curpos + char_rect.right * fontsize / 1000;
if (min_x > char_left) {
min_x = char_left;
}
if (max_x < char_left) {
max_x = char_left;
}
if (min_x > char_right) {
min_x = char_right;
}
if (max_x < char_right) {
max_x = char_right;
}
charwidth = pFont->GetCharWidthF(charcode, level) * fontsize / 1000;
} else {
FX_WORD CID = pCIDFont->CIDFromCharCode(charcode);
short vx;
short vy;
pCIDFont->GetVertOrigin(CID, vx, vy);
char_rect.left -= vx;
char_rect.right -= vx;
char_rect.top -= vy;
char_rect.bottom -= vy;
if (min_x > char_rect.left) {
min_x = (FX_FLOAT)char_rect.left;
}
if (max_x < char_rect.left) {
max_x = (FX_FLOAT)char_rect.left;
}
if (min_x > char_rect.right) {
min_x = (FX_FLOAT)char_rect.right;
}
if (max_x < char_rect.right) {
max_x = (FX_FLOAT)char_rect.right;
}
FX_FLOAT char_top = curpos + char_rect.top * fontsize / 1000;
FX_FLOAT char_bottom = curpos + char_rect.bottom * fontsize / 1000;
if (min_y > char_top) {
min_y = char_top;
}
if (max_y < char_top) {
max_y = char_top;
}
if (min_y > char_bottom) {
min_y = char_bottom;
}
if (max_y < char_bottom) {
max_y = char_bottom;
}
charwidth = pCIDFont->GetVertWidth(CID) * fontsize / 1000;
}
curpos += charwidth;
if (charcode == ' ' && (!pCIDFont || pCIDFont->GetCharSize(32) == 1)) {
curpos += m_TextState.GetObject()->m_WordSpace;
}
curpos += m_TextState.GetObject()->m_CharSpace;
}
if (bVertWriting) {
if (pTextAdvanceX) {
*pTextAdvanceX = 0;
}
if (pTextAdvanceY) {
*pTextAdvanceY = curpos;
}
min_x = min_x * fontsize / 1000;
max_x = max_x * fontsize / 1000;
} else {
if (pTextAdvanceX) {
*pTextAdvanceX = FXSYS_Mul(curpos, horz_scale);
}
if (pTextAdvanceY) {
*pTextAdvanceY = 0;
}
min_y = min_y * fontsize / 1000;
max_y = max_y * fontsize / 1000;
}
CFX_AffineMatrix matrix;
GetTextMatrix(&matrix);
m_Left = min_x;
m_Right = max_x;
m_Bottom = min_y;
m_Top = max_y;
matrix.TransformRect(m_Left, m_Right, m_Top, m_Bottom);
int textmode = m_TextState.GetObject()->m_TextMode;
if (textmode == 1 || textmode == 2 || textmode == 5 || textmode == 6) {
FX_FLOAT half_width = m_GraphState.GetObject()->m_LineWidth / 2;
m_Left -= half_width;
m_Right += half_width;
m_Top += half_width;
m_Bottom -= half_width;
}
}
示例12: FXSYS_fabs
void CFX_PSRenderer::FindPSFontGlyph(CFX_FaceCache* pFaceCache, CFX_Font* pFont, const FXTEXT_CHARPOS& charpos,
int& ps_fontnum, int &ps_glyphindex)
{
for (int i = 0; i < (int)m_PSFontList.GetSize(); i ++) {
CPSFont* pPSFont = m_PSFontList[i];
for (int j = 0; j < pPSFont->m_nGlyphs; j ++)
if (pPSFont->m_Glyphs[j].m_pFont == pFont && pPSFont->m_Glyphs[j].m_GlyphIndex == charpos.m_GlyphIndex) {
if ((!pPSFont->m_Glyphs[j].m_bGlyphAdjust && !charpos.m_bGlyphAdjust) ||
(pPSFont->m_Glyphs[j].m_bGlyphAdjust && charpos.m_bGlyphAdjust &&
(FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[0] - charpos.m_AdjustMatrix[0]) < 0.01 &&
FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[1] - charpos.m_AdjustMatrix[1]) < 0.01 &&
FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[2] - charpos.m_AdjustMatrix[2]) < 0.01 &&
FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[3] - charpos.m_AdjustMatrix[3]) < 0.01))) {
ps_fontnum = i;
ps_glyphindex = j;
return;
}
}
}
if (m_PSFontList.GetSize() == 0 || m_PSFontList[m_PSFontList.GetSize() - 1]->m_nGlyphs == 256) {
CPSFont* pPSFont = new CPSFont;
pPSFont->m_nGlyphs = 0;
m_PSFontList.Add(pPSFont);
CFX_ByteTextBuf buf;
buf << FX_BSTRC("8 dict begin/FontType 3 def/FontMatrix[1 0 0 1 0 0]def\n"
"/FontBBox[0 0 0 0]def/Encoding 256 array def 0 1 255{Encoding exch/.notdef put}for\n"
"/CharProcs 1 dict def CharProcs begin/.notdef {} def end\n"
"/BuildGlyph{1 0 -10 -10 10 10 setcachedevice exch/CharProcs get exch 2 copy known not{pop/.notdef}if get exec}bind def\n"
"/BuildChar{1 index/Encoding get exch get 1 index/BuildGlyph get exec}bind def\n"
"currentdict end\n");
buf << FX_BSTRC("/X") << m_PSFontList.GetSize() - 1 << FX_BSTRC(" exch definefont pop\n");
m_pOutput->OutputPS((FX_LPCSTR)buf.GetBuffer(), buf.GetSize());
buf.Clear();
}
ps_fontnum = m_PSFontList.GetSize() - 1;
CPSFont* pPSFont = m_PSFontList[ps_fontnum];
ps_glyphindex = pPSFont->m_nGlyphs;
pPSFont->m_Glyphs[ps_glyphindex].m_GlyphIndex = charpos.m_GlyphIndex;
pPSFont->m_Glyphs[ps_glyphindex].m_pFont = pFont;
pPSFont->m_Glyphs[ps_glyphindex].m_bGlyphAdjust = charpos.m_bGlyphAdjust;
if (charpos.m_bGlyphAdjust) {
pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[0] = charpos.m_AdjustMatrix[0];
pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[1] = charpos.m_AdjustMatrix[1];
pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[2] = charpos.m_AdjustMatrix[2];
pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[3] = charpos.m_AdjustMatrix[3];
}
pPSFont->m_nGlyphs ++;
CFX_AffineMatrix matrix;
if (charpos.m_bGlyphAdjust)
matrix.Set(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1],
charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0);
matrix.Concat(1.0f, 0, 0, 1.0f, 0, 0);
const CFX_PathData* pPathData = pFaceCache->LoadGlyphPath(pFont, charpos.m_GlyphIndex, charpos.m_FontCharWidth);
if (pPathData == NULL) {
return;
}
CFX_PathData TransformedPath(*pPathData);
if (charpos.m_bGlyphAdjust) {
TransformedPath.Transform(&matrix);
}
CFX_ByteTextBuf buf;
buf << FX_BSTRC("/X") << ps_fontnum << FX_BSTRC(" Ff/CharProcs get begin/")
<< ps_glyphindex << FX_BSTRC("{");
buf << FX_BSTRC("n ");
for (int p = 0; p < TransformedPath.GetPointCount(); p ++) {
FX_FLOAT x = TransformedPath.GetPointX(p), y = TransformedPath.GetPointY(p);
switch (TransformedPath.GetFlag(p) & FXPT_TYPE) {
case FXPT_MOVETO: {
buf << x << FX_BSTRC(" ") << y << FX_BSTRC(" m\n");
break;
}
case FXPT_LINETO: {
buf << x << FX_BSTRC(" ") << y << FX_BSTRC(" l\n");
break;
}
case FXPT_BEZIERTO: {
buf << x << FX_BSTRC(" ") << y << FX_BSTRC(" ")
<< TransformedPath.GetPointX(p + 1) << FX_BSTRC(" ")
<< TransformedPath.GetPointY(p + 1) << FX_BSTRC(" ")
<< TransformedPath.GetPointX(p + 2) << FX_BSTRC(" ")
<< TransformedPath.GetPointY(p + 2) << FX_BSTRC(" c\n");
p += 2;
break;
}
}
}
buf << FX_BSTRC("f");
buf << FX_BSTRC("}bind def end\n");
buf << FX_BSTRC("/X") << ps_fontnum << FX_BSTRC(" Ff/Encoding get ") << ps_glyphindex
<< FX_BSTRC("/") << ps_glyphindex << FX_BSTRC(" put\n");
m_pOutput->OutputPS((FX_LPCSTR)buf.GetBuffer(), buf.GetSize());
}
示例13: ProcessObject
FX_BOOL CPDF_TextStream::ProcessObject(const CPDF_TextObject* pObj, FX_BOOL bFirstLine)
{
CPDF_Font* pFont = pObj->GetFont();
CFX_AffineMatrix matrix;
pObj->GetTextMatrix(&matrix);
int item_index = 0;
if (m_pLastObj) {
int result = FPDFText_ProcessInterObj(m_pLastObj, pObj);
if (result == 2) {
int len = m_Buffer.GetLength();
if (len && m_bUseLF && m_Buffer.GetBuffer()[len - 1] == L'-') {
m_Buffer.Delete(len - 1, 1);
if (m_pObjArray) {
m_pObjArray->RemoveAt((len - 1) * 2, 2);
}
} else {
if (bFirstLine) {
return TRUE;
}
if (m_bUseLF) {
m_Buffer.AppendChar(L'\r');
m_Buffer.AppendChar(L'\n');
if (m_pObjArray) {
for (int i = 0; i < 4; i ++) {
m_pObjArray->Add(NULL);
}
}
} else {
m_Buffer.AppendChar(' ');
if (m_pObjArray) {
m_pObjArray->Add(NULL);
m_pObjArray->Add(NULL);
}
}
}
} else if (result == 1) {
m_Buffer.AppendChar(L' ');
if (m_pObjArray) {
m_pObjArray->Add(NULL);
m_pObjArray->Add(NULL);
}
} else if (result == -1) {
m_pLastObj = pObj;
return FALSE;
} else if (result == 3) {
item_index = 1;
}
}
m_pLastObj = pObj;
int nItems = pObj->CountItems();
FX_FLOAT Ignorekerning = 0;
for(int i = 1; i < nItems - 1; i += 2) {
CPDF_TextObjectItem item;
pObj->GetItemInfo(i, &item);
if (item.m_CharCode == (FX_DWORD) - 1) {
if(i == 1) {
Ignorekerning = item.m_OriginX;
} else if(Ignorekerning > item.m_OriginX) {
Ignorekerning = item.m_OriginX;
}
} else {
Ignorekerning = 0;
break;
}
}
FX_FLOAT spacing = 0;
for (; item_index < nItems; item_index ++) {
CPDF_TextObjectItem item;
pObj->GetItemInfo(item_index, &item);
if (item.m_CharCode == (FX_DWORD) - 1) {
CFX_WideString wstr = m_Buffer.GetWideString();
if (wstr.IsEmpty() || wstr.GetAt(wstr.GetLength() - 1) == L' ') {
continue;
}
FX_FLOAT fontsize_h = pObj->m_TextState.GetFontSizeH();
spacing = -fontsize_h * (item.m_OriginX - Ignorekerning) / 1000;
continue;
}
FX_FLOAT charSpace = pObj->m_TextState.GetObject()->m_CharSpace;
if(nItems > 3 && !spacing) {
charSpace = 0;
}
if((spacing || charSpace) && item_index > 0) {
int last_width = 0;
FX_FLOAT fontsize_h = pObj->m_TextState.GetFontSizeH();
FX_DWORD space_charcode = pFont->CharCodeFromUnicode(' ');
FX_FLOAT threshold = 0;
if (space_charcode != -1) {
threshold = fontsize_h * pFont->GetCharWidthF(space_charcode) / 1000 ;
}
if(threshold > fontsize_h / 3) {
threshold = 0;
} else {
threshold /= 2;
}
if (threshold == 0) {
threshold = fontsize_h;
int this_width = FXSYS_abs(GetCharWidth(item.m_CharCode, pFont));
threshold = this_width > last_width ? (FX_FLOAT)this_width : (FX_FLOAT)last_width;
int nDivide = 6;
//.........这里部分代码省略.........
示例14: DrawRadialShading
static void DrawRadialShading(CFX_DIBitmap* pBitmap,
CFX_AffineMatrix* pObject2Bitmap,
CPDF_Dictionary* pDict,
CPDF_Function** pFuncs,
int nFuncs,
CPDF_ColorSpace* pCS,
int alpha) {
ASSERT(pBitmap->GetFormat() == FXDIB_Argb);
CPDF_Array* pCoords = pDict->GetArray(FX_BSTRC("Coords"));
if (pCoords == NULL) {
return;
}
FX_FLOAT start_x = pCoords->GetNumber(0);
FX_FLOAT start_y = pCoords->GetNumber(1);
FX_FLOAT start_r = pCoords->GetNumber(2);
FX_FLOAT end_x = pCoords->GetNumber(3);
FX_FLOAT end_y = pCoords->GetNumber(4);
FX_FLOAT end_r = pCoords->GetNumber(5);
CFX_AffineMatrix matrix;
matrix.SetReverse(*pObject2Bitmap);
FX_FLOAT t_min = 0, t_max = 1.0f;
CPDF_Array* pArray = pDict->GetArray(FX_BSTRC("Domain"));
if (pArray) {
t_min = pArray->GetNumber(0);
t_max = pArray->GetNumber(1);
}
FX_BOOL bStartExtend = FALSE, bEndExtend = FALSE;
pArray = pDict->GetArray(FX_BSTRC("Extend"));
if (pArray) {
bStartExtend = pArray->GetInteger(0);
bEndExtend = pArray->GetInteger(1);
}
int total_results = 0;
for (int j = 0; j < nFuncs; j++) {
if (pFuncs[j]) {
total_results += pFuncs[j]->CountOutputs();
}
}
if (pCS->CountComponents() > total_results) {
total_results = pCS->CountComponents();
}
CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results);
FX_FLOAT* pResults = result_array;
FXSYS_memset(pResults, 0, total_results * sizeof(FX_FLOAT));
FX_DWORD rgb_array[SHADING_STEPS];
for (int i = 0; i < SHADING_STEPS; i++) {
FX_FLOAT input = (t_max - t_min) * i / SHADING_STEPS + t_min;
int offset = 0;
for (int j = 0; j < nFuncs; j++) {
if (pFuncs[j]) {
int nresults;
if (pFuncs[j]->Call(&input, 1, pResults + offset, nresults)) {
offset += nresults;
}
}
}
FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f;
pCS->GetRGB(pResults, R, G, B);
rgb_array[i] =
FXARGB_TODIB(FXARGB_MAKE(alpha, FXSYS_round(R * 255),
FXSYS_round(G * 255), FXSYS_round(B * 255)));
}
FX_FLOAT a = FXSYS_Mul(start_x - end_x, start_x - end_x) +
FXSYS_Mul(start_y - end_y, start_y - end_y) -
FXSYS_Mul(start_r - end_r, start_r - end_r);
int width = pBitmap->GetWidth();
int height = pBitmap->GetHeight();
int pitch = pBitmap->GetPitch();
FX_BOOL bDecreasing = FALSE;
if (start_r > end_r) {
int length = (int)FXSYS_sqrt((FXSYS_Mul(start_x - end_x, start_x - end_x) +
FXSYS_Mul(start_y - end_y, start_y - end_y)));
if (length < start_r - end_r) {
bDecreasing = TRUE;
}
}
for (int row = 0; row < height; row++) {
FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch);
for (int column = 0; column < width; column++) {
FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row;
matrix.Transform(x, y);
FX_FLOAT b = -2 * (FXSYS_Mul(x - start_x, end_x - start_x) +
FXSYS_Mul(y - start_y, end_y - start_y) +
FXSYS_Mul(start_r, end_r - start_r));
FX_FLOAT c = FXSYS_Mul(x - start_x, x - start_x) +
FXSYS_Mul(y - start_y, y - start_y) -
FXSYS_Mul(start_r, start_r);
FX_FLOAT s;
if (a == 0) {
s = FXSYS_Div(-c, b);
} else {
FX_FLOAT b2_4ac = FXSYS_Mul(b, b) - 4 * FXSYS_Mul(a, c);
if (b2_4ac < 0) {
continue;
}
FX_FLOAT root = FXSYS_sqrt(b2_4ac);
FX_FLOAT s1, s2;
if (a > 0) {
s1 = FXSYS_Div(-b - root, 2 * a);
s2 = FXSYS_Div(-b + root, 2 * a);
//.........这里部分代码省略.........
示例15: FX_BSTRC
CFX_DIBitmap* CPDF_RenderStatus::LoadSMask(CPDF_Dictionary* pSMaskDict,
FX_RECT* pClipRect, const CFX_AffineMatrix* pMatrix)
{
if (pSMaskDict == NULL) {
return NULL;
}
CFX_DIBitmap* pMask = NULL;
int width = pClipRect->right - pClipRect->left;
int height = pClipRect->bottom - pClipRect->top;
FX_BOOL bLuminosity = FALSE;
bLuminosity = pSMaskDict->GetConstString(FX_BSTRC("S")) != FX_BSTRC("Alpha");
CPDF_Stream* pGroup = pSMaskDict->GetStream(FX_BSTRC("G"));
if (pGroup == NULL) {
return NULL;
}
CPDF_Function* pFunc = NULL;
CPDF_Object* pFuncObj = pSMaskDict->GetElementValue(FX_BSTRC("TR"));
if (pFuncObj && (pFuncObj->GetType() == PDFOBJ_DICTIONARY || pFuncObj->GetType() == PDFOBJ_STREAM)) {
pFunc = CPDF_Function::Load(pFuncObj);
}
CFX_AffineMatrix matrix = *pMatrix;
matrix.TranslateI(-pClipRect->left, -pClipRect->top);
CPDF_Form form(m_pContext->m_pDocument, m_pContext->m_pPageResources, pGroup);
form.ParseContent(NULL, NULL, NULL, NULL);
CFX_FxgeDevice bitmap_device;
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
if (!bitmap_device.Create(width, height, bLuminosity ? FXDIB_Rgb32 : FXDIB_8bppMask)) {
return NULL;
}
#else
if (!bitmap_device.Create(width, height, bLuminosity ? FXDIB_Rgb : FXDIB_8bppMask)) {
return NULL;
}
#endif
CFX_DIBitmap& bitmap = *bitmap_device.GetBitmap();
CPDF_Object* pCSObj = NULL;
CPDF_ColorSpace* pCS = NULL;
if (bLuminosity) {
CPDF_Array* pBC = pSMaskDict->GetArray(FX_BSTRC("BC"));
FX_ARGB back_color = 0xff000000;
if (pBC) {
pCSObj = pGroup->GetDict()->GetDict(FX_BSTRC("Group"))->GetElementValue(FX_BSTRC("CS"));
pCS = m_pContext->m_pDocument->LoadColorSpace(pCSObj);
if (pCS) {
FX_FLOAT R, G, B;
FX_DWORD num_floats = 8;
if (pCS->CountComponents() > (FX_INT32)num_floats) {
num_floats = (FX_DWORD)pCS->CountComponents();
}
CFX_FixedBufGrow<FX_FLOAT, 8> float_array(num_floats);
FX_FLOAT* pFloats = float_array;
FXSYS_memset32(pFloats, 0, num_floats * sizeof(FX_FLOAT));
int count = pBC->GetCount() > 8 ? 8 : pBC->GetCount();
for (int i = 0; i < count; i ++) {
pFloats[i] = pBC->GetNumber(i);
}
pCS->GetRGB(pFloats, R, G, B);
back_color = 0xff000000 | ((FX_INT32)(R * 255) << 16) | ((FX_INT32)(G * 255) << 8) | (FX_INT32)(B * 255);
m_pContext->m_pDocument->GetPageData()->ReleaseColorSpace(pCSObj);
}
}
bitmap.Clear(back_color);
} else {
bitmap.Clear(0);
}
CPDF_Dictionary* pFormResource = NULL;
if (form.m_pFormDict) {
pFormResource = form.m_pFormDict->GetDict(FX_BSTRC("Resources"));
}
CPDF_RenderOptions options;
options.m_ColorMode = bLuminosity ? RENDER_COLOR_NORMAL : RENDER_COLOR_ALPHA;
CPDF_RenderStatus status;
status.Initialize(m_Level + 1, m_pContext, &bitmap_device, NULL, NULL, NULL, NULL,
&options, 0, m_bDropObjects, pFormResource, TRUE, NULL, 0, pCS ? pCS->GetFamily() : 0, bLuminosity);
status.RenderObjectList(&form, &matrix);
pMask = FX_NEW CFX_DIBitmap;
if (!pMask->Create(width, height, FXDIB_8bppMask)) {
delete pMask;
return NULL;
}
FX_LPBYTE dest_buf = pMask->GetBuffer();
int dest_pitch = pMask->GetPitch();
FX_LPBYTE src_buf = bitmap.GetBuffer();
int src_pitch = bitmap.GetPitch();
FX_LPBYTE pTransfer = FX_Alloc(FX_BYTE, 256);
if (pFunc) {
CFX_FixedBufGrow<FX_FLOAT, 16> results(pFunc->CountOutputs());
for (int i = 0; i < 256; i ++) {
FX_FLOAT input = (FX_FLOAT)i / 255.0f;
int nresult;
pFunc->Call(&input, 1, results, nresult);
pTransfer[i] = FXSYS_round(results[0] * 255);
}
} else {
for (int i = 0; i < 256; i ++) {
pTransfer[i] = i;
}
}
if (bLuminosity) {
int Bpp = bitmap.GetBPP() / 8;
//.........这里部分代码省略.........